| File: | ui/GameUI.cpp |
| Warning: | line 14236, column 26 Wrong iterator dereferenced |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | // GameUI.cpp | |||
| 2 | ||||
| 3 | #include "GameUI.hpp" | |||
| 4 | #include "MainMenu.hpp" | |||
| 5 | #include "Frame.hpp" | |||
| 6 | #include "Image.hpp" | |||
| 7 | #include "Field.hpp" | |||
| 8 | #include "Button.hpp" | |||
| 9 | #include "Text.hpp" | |||
| 10 | #include "Slider.hpp" | |||
| 11 | #include "Widget.hpp" | |||
| 12 | ||||
| 13 | #include "../main.hpp" | |||
| 14 | #include "../game.hpp" | |||
| 15 | #include "../menu.hpp" | |||
| 16 | #include "../interface/interface.hpp" | |||
| 17 | #include "../interface/consolecommand.hpp" | |||
| 18 | #include "../stat.hpp" | |||
| 19 | #include "../player.hpp" | |||
| 20 | #include "../draw.hpp" | |||
| 21 | #include "../items.hpp" | |||
| 22 | #include "../mod_tools.hpp" | |||
| 23 | #include "../input.hpp" | |||
| 24 | #include "../collision.hpp" | |||
| 25 | #include "../monster.hpp" | |||
| 26 | #include "../classdescriptions.hpp" | |||
| 27 | #include "../shops.hpp" | |||
| 28 | #include "../colors.hpp" | |||
| 29 | #include "../book.hpp" | |||
| 30 | ||||
| 31 | #include <assert.h> | |||
| 32 | ||||
| 33 | const Uint32 playerColor(int index, bool colorblind, bool ally) | |||
| 34 | { | |||
| 35 | Uint32 result; | |||
| 36 | if (colorblind) { | |||
| 37 | switch (index) { | |||
| 38 | default: result = uint32ColorPlayerX_colorblind; break; | |||
| 39 | case 0: result = uint32ColorPlayer1_colorblind; break; | |||
| 40 | case 1: result = uint32ColorPlayer2_colorblind; break; | |||
| 41 | case 2: result = uint32ColorPlayer3_colorblind; break; | |||
| 42 | case 3: result = uint32ColorPlayer4_colorblind; break; | |||
| 43 | case 4: result = uint32ColorPlayer5_colorblind; break; | |||
| 44 | case 5: result = uint32ColorPlayer6_colorblind; break; | |||
| 45 | case 6: result = uint32ColorPlayer7_colorblind; break; | |||
| 46 | case 7: result = uint32ColorPlayer8_colorblind; break; | |||
| 47 | } | |||
| 48 | } | |||
| 49 | else { | |||
| 50 | switch (index) { | |||
| 51 | default: result = uint32ColorPlayerX; break; | |||
| 52 | case 0: result = uint32ColorPlayer1; break; | |||
| 53 | case 1: result = uint32ColorPlayer2; break; | |||
| 54 | case 2: result = uint32ColorPlayer3; break; | |||
| 55 | case 3: result = uint32ColorPlayer4; break; | |||
| 56 | case 4: result = uint32ColorPlayer5; break; | |||
| 57 | case 5: result = uint32ColorPlayer6; break; | |||
| 58 | case 6: result = uint32ColorPlayer7; break; | |||
| 59 | case 7: result = uint32ColorPlayer8; break; | |||
| 60 | } | |||
| 61 | } | |||
| 62 | if (ally) { | |||
| 63 | uint8_t r, g, b, a; | |||
| 64 | getColor(result, &r, &g, &b, &a); | |||
| 65 | r /= 2; g /= 2; b /= 2; | |||
| 66 | return makeColor(r, g, b, a); | |||
| 67 | } else { | |||
| 68 | return result; | |||
| 69 | } | |||
| 70 | } | |||
| 71 | ||||
| 72 | static const char* bigfont_outline = "fonts/pixelmix.ttf#16#2"; | |||
| 73 | static const char* bigfont_no_outline = "fonts/pixelmix.ttf#16#0"; | |||
| 74 | static const char* smallfont_outline = "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 75 | static const char* smallfont_no_outline = "fonts/pixel_maz_multiline.ttf#16#0"; | |||
| 76 | ||||
| 77 | static ConsoleVariable<Vector4> mapBgColor("/map_background_color", Vector4{22.f, 24.f, 29.f, 223.f}); | |||
| 78 | static ConsoleVariable<Vector4> logBgColor("/log_background_color", Vector4{22.f, 24.f, 29.f, 223.f}); | |||
| 79 | static ConsoleVariable<bool> cvar_hotbar_compact_disable("/hotbar_compact_disable", false); // dont use compact at all | |||
| 80 | static ConsoleVariable<bool> cvar_hotbar_compact_use_fullsize("/hotbar_compact_fullsize", true); // dont use extra compact view, just normal compact | |||
| 81 | ||||
| 82 | Frame* gameUIFrame[MAXPLAYERS4] = { nullptr }; | |||
| 83 | bool newui = true; | |||
| 84 | int selectedCursorOpacity = 255; | |||
| 85 | int oldSelectedCursorOpacity = 255; | |||
| 86 | int hotbarSlotOpacity = 255; | |||
| 87 | int hotbarSelectedSlotOpacity = 255; | |||
| 88 | int hotbarCompactOffsetX = 0; | |||
| 89 | real_t hotbarCompactSlotOverlapPercent = 0.0; // % of a slot to overlap facemenu buttons in compact view | |||
| 90 | int hotbarCompactInactiveSlotMovementX = 0; // inactive facemenu groups move over by this much out of the way in compact view | |||
| 91 | int hotbarCompactExpandedOffsetX = 0; // navigating the hotbar in inventory mode will expand the centers of groups out by this much | |||
| 92 | int hotbarOffsetY = 0; | |||
| 93 | int hotbarCompactOffsetY = 0; | |||
| 94 | ||||
| 95 | int xpbarOffsetWidth = 0; | |||
| 96 | int xpbarOffsetY = 0; | |||
| 97 | int xpbarCompactOffsetWidth = 0; | |||
| 98 | int xpbarCompactOffsetY = 0; | |||
| 99 | ||||
| 100 | int hpmpbarOffsetWidth = 0; | |||
| 101 | int hpmpbarOffsetX = 0; | |||
| 102 | int hpmpbarOffsetY = 0; | |||
| 103 | int hpmpbarCompactOffsetWidth = 0; | |||
| 104 | int hpmpbarCompactOffsetX = 0; | |||
| 105 | int hpmpbarCompactOffsetY = 0; | |||
| 106 | ||||
| 107 | int hpmpbarMaxWidthAmount = 160; // hp / mp value that makes the bar 100% size | |||
| 108 | int hpmpbarIntervalToIncreaseWidth = 5; // hp / mp grows every x max hp/mp value | |||
| 109 | int hpmpbarIntervalStartValue = 20; // hp / mp of this value is the smallest interval | |||
| 110 | int hpmpbarBasePercentSize = 30; // smallest width at low hp/mp value | |||
| 111 | real_t hpmpbarWidthIncreasePercentOnInterval = 2.5; // % to grow bar per interval | |||
| 112 | int hpmpbarCompactMaxWidthAmount = 160; // hp / mp value that makes the bar 100% size | |||
| 113 | int hpmpbarCompactIntervalToIncreaseWidth = 5; // hp / mp grows every x max hp/mp value | |||
| 114 | int hpmpbarCompactIntervalStartValue = 20; // hp / mp of this value is the smallest interval | |||
| 115 | int hpmpbarCompactBasePercentSize = 44; // smallest width at low hp/mp value | |||
| 116 | real_t hpmpbarCompactWidthIncreasePercentOnInterval = 2.0; // % to grow bar per interval | |||
| 117 | ||||
| 118 | struct AllyStatusBarSettings_t | |||
| 119 | { | |||
| 120 | struct HPBar_t | |||
| 121 | { | |||
| 122 | int barPixelWidth = 120; // pixel width of bar | |||
| 123 | int barCompactPixelWidth = 120; // pixel width of bar | |||
| 124 | int barSplitscreenPixelWidthOffset = 0; // amount to shrink bars in compact width mode | |||
| 125 | int barMaxWidthAmount = 160; // hp / mp value that makes the bar 100% size | |||
| 126 | int barIntervalToIncreaseWidth = 5; // hp / mp grows every x max hp/mp value | |||
| 127 | int barIntervalStartValue = 20; // hp / mp of this value is the smallest interval | |||
| 128 | int barBasePercentSize = 30; // smallest width at low hp/mp value | |||
| 129 | real_t barWidthIncreasePercentOnInterval = 2.5; // % to grow bar per interval | |||
| 130 | int barCompactMaxWidthAmount = 160; // hp / mp value that makes the bar 100% size | |||
| 131 | int barCompactIntervalToIncreaseWidth = 5; // hp / mp grows every x max hp/mp value | |||
| 132 | int barCompactIntervalStartValue = 20; // hp / mp of this value is the smallest interval | |||
| 133 | int barCompactBasePercentSize = 44; // smallest width at low hp/mp value | |||
| 134 | real_t barCompactWidthIncreasePercentOnInterval = 2.0; // % to grow bar per interval | |||
| 135 | }; | |||
| 136 | struct MPBar_t | |||
| 137 | { | |||
| 138 | int barPixelWidth = 120; // pixel width of bar | |||
| 139 | int barCompactPixelWidth = 120; // pixel width of bar | |||
| 140 | int barMaxWidthAmount = 160; // hp / mp value that makes the bar 100% size | |||
| 141 | int barIntervalToIncreaseWidth = 5; // hp / mp grows every x max hp/mp value | |||
| 142 | int barIntervalStartValue = 20; // hp / mp of this value is the smallest interval | |||
| 143 | int barBasePercentSize = 30; // smallest width at low hp/mp value | |||
| 144 | real_t barWidthIncreasePercentOnInterval = 2.5; // % to grow bar per interval | |||
| 145 | int barCompactMaxWidthAmount = 160; // hp / mp value that makes the bar 100% size | |||
| 146 | int barCompactIntervalToIncreaseWidth = 5; // hp / mp grows every x max hp/mp value | |||
| 147 | int barCompactIntervalStartValue = 20; // hp / mp of this value is the smallest interval | |||
| 148 | int barCompactBasePercentSize = 44; // smallest width at low hp/mp value | |||
| 149 | real_t barCompactWidthIncreasePercentOnInterval = 2.0; // % to grow bar per interval | |||
| 150 | }; | |||
| 151 | struct EntrySettings_t | |||
| 152 | { | |||
| 153 | int entryHeight = 40; | |||
| 154 | int entryCompactHeight = 40; | |||
| 155 | int maxNameLengthFullsize = 10; | |||
| 156 | int maxNameLengthCompact = 10; | |||
| 157 | int maxNameLengthSplitscreenFullsize = 10; | |||
| 158 | int maxNameLengthSplitscreenCompact = 10; | |||
| 159 | int baseY = 20; | |||
| 160 | int baseYSplitscreen = 20; | |||
| 161 | }; | |||
| 162 | struct FollowerBars_t | |||
| 163 | { | |||
| 164 | static EntrySettings_t entrySettings; | |||
| 165 | static HPBar_t hpBar; | |||
| 166 | static MPBar_t mpBar; | |||
| 167 | }; | |||
| 168 | struct PlayerBars_t | |||
| 169 | { | |||
| 170 | static EntrySettings_t entrySettings; | |||
| 171 | static HPBar_t hpBar; | |||
| 172 | static MPBar_t mpBar; | |||
| 173 | }; | |||
| 174 | }; | |||
| 175 | AllyStatusBarSettings_t::EntrySettings_t AllyStatusBarSettings_t::FollowerBars_t::entrySettings; | |||
| 176 | AllyStatusBarSettings_t::EntrySettings_t AllyStatusBarSettings_t::PlayerBars_t::entrySettings; | |||
| 177 | AllyStatusBarSettings_t::HPBar_t AllyStatusBarSettings_t::FollowerBars_t::hpBar; | |||
| 178 | AllyStatusBarSettings_t::MPBar_t AllyStatusBarSettings_t::FollowerBars_t::mpBar; | |||
| 179 | AllyStatusBarSettings_t::HPBar_t AllyStatusBarSettings_t::PlayerBars_t::hpBar; | |||
| 180 | AllyStatusBarSettings_t::MPBar_t AllyStatusBarSettings_t::PlayerBars_t::mpBar; | |||
| 181 | ||||
| 182 | struct MessageZoneSettings_t | |||
| 183 | { | |||
| 184 | enum HotbarTypes_t : int { | |||
| 185 | HOTBAR_CLASSIC, | |||
| 186 | HOTBAR_MODERN_GAMEPAD, | |||
| 187 | HOTBAR_MODERN_KEYBOARD | |||
| 188 | }; | |||
| 189 | struct MessageSettings_t | |||
| 190 | { | |||
| 191 | HotbarTypes_t hotbarType = HOTBAR_CLASSIC; | |||
| 192 | Player::MessageZone_t::ChatAlignment_t alignment = Player::MessageZone_t::ALIGN_LEFT_BOTTOM; | |||
| 193 | enum LayoutType_t : int { | |||
| 194 | LAYOUT_DEFAULT, | |||
| 195 | LAYOUT_COMPACT | |||
| 196 | }; | |||
| 197 | struct Layout_t | |||
| 198 | { | |||
| 199 | LayoutType_t layoutType = LAYOUT_DEFAULT; | |||
| 200 | int offsetY = 0; | |||
| 201 | int maxMessages = 10; | |||
| 202 | }; | |||
| 203 | std::map<LayoutType_t, Layout_t> layouts; | |||
| 204 | }; | |||
| 205 | std::map<HotbarTypes_t, std::map<Player::MessageZone_t::ChatAlignment_t, MessageSettings_t>> settings; | |||
| 206 | MessageSettings_t& addSetting(const HotbarTypes_t _hotbarType, const Player::MessageZone_t::ChatAlignment_t _alignment) | |||
| 207 | { | |||
| 208 | settings[_hotbarType][_alignment] = MessageSettings_t(); | |||
| 209 | auto& setting = settings[_hotbarType][_alignment]; | |||
| 210 | setting.hotbarType = _hotbarType; | |||
| 211 | setting.alignment = _alignment; | |||
| 212 | return setting; | |||
| 213 | } | |||
| 214 | MessageSettings_t::Layout_t& getLayout(const int player, const Player::MessageZone_t::ChatAlignment_t _alignment) | |||
| 215 | { | |||
| 216 | bool compact = players[player]->bUseCompactGUIHeight(); | |||
| 217 | auto layout = compact ? MessageSettings_t::LayoutType_t::LAYOUT_COMPACT : MessageSettings_t::LayoutType_t::LAYOUT_DEFAULT; | |||
| 218 | if ( players[player]->hotbar.useHotbarFaceMenu ) | |||
| 219 | { | |||
| 220 | if ( inputs.hasController(player) ) | |||
| 221 | { | |||
| 222 | return settings[HOTBAR_MODERN_GAMEPAD][_alignment].layouts[layout]; | |||
| 223 | } | |||
| 224 | else | |||
| 225 | { | |||
| 226 | return settings[HOTBAR_MODERN_KEYBOARD][_alignment].layouts[layout]; | |||
| 227 | } | |||
| 228 | } | |||
| 229 | else | |||
| 230 | { | |||
| 231 | return settings[HOTBAR_CLASSIC][_alignment].layouts[layout]; | |||
| 232 | } | |||
| 233 | } | |||
| 234 | }; | |||
| 235 | MessageZoneSettings_t messageZoneSettings; | |||
| 236 | ||||
| 237 | struct DamageIndicatorSettings_t | |||
| 238 | { | |||
| 239 | enum LayoutType_t : int { | |||
| 240 | LAYOUT_DEFAULT, | |||
| 241 | LAYOUT_2P_WIDE, | |||
| 242 | LAYOUT_2P_TALL, | |||
| 243 | LAYOUT_4P | |||
| 244 | }; | |||
| 245 | struct Layout_t | |||
| 246 | { | |||
| 247 | int image_size = 3; | |||
| 248 | int radius_x = 200; | |||
| 249 | int radius_y = 200; | |||
| 250 | }; | |||
| 251 | std::map<LayoutType_t, Layout_t> settings; | |||
| 252 | real_t fadeSpeed = 1.0; | |||
| 253 | Uint32 fadeAfterTicks = HITRATE45; | |||
| 254 | Uint32 deleteAfterTicks = 45; | |||
| 255 | std::string indicatorDamageFramePaths[4] = { | |||
| 256 | "images/ui/HUD/indicators/damageB", | |||
| 257 | "images/ui/HUD/indicators/damage", | |||
| 258 | "images/ui/HUD/indicators/damage", | |||
| 259 | "images/ui/HUD/indicators/damage" | |||
| 260 | }; | |||
| 261 | std::string indicatorBlockedFramePaths[4] = { | |||
| 262 | "images/ui/HUD/indicators/damage_blocked", | |||
| 263 | "images/ui/HUD/indicators/damage_blocked", | |||
| 264 | "images/ui/HUD/indicators/damage_blocked", | |||
| 265 | "images/ui/HUD/indicators/damage_blocked" | |||
| 266 | }; | |||
| 267 | }; | |||
| 268 | DamageIndicatorSettings_t damageIndicatorSettings; | |||
| 269 | ||||
| 270 | std::vector<int> LevelUpAnimBreakpoints; | |||
| 271 | LevelUpAnimation_t levelUpAnimation[MAXPLAYERS4]; | |||
| 272 | ||||
| 273 | std::map<Player::WorldUI_t::WorldTooltipDialogue_t::DialogueType_t, | |||
| 274 | Player::WorldUI_t::WorldTooltipDialogue_t::WorldDialogueSettings_t::Setting_t> Player::WorldUI_t::WorldTooltipDialogue_t::WorldDialogueSettings_t::settings; | |||
| 275 | real_t Player::WorldUI_t::WorldTooltipItem_t::WorldItemSettings_t::scaleMod = 0.0; | |||
| 276 | real_t Player::WorldUI_t::WorldTooltipItem_t::WorldItemSettings_t::opacity = 0.0; | |||
| 277 | ||||
| 278 | bool bUsePreciseFieldTextReflow = true; | |||
| 279 | bool bUseSelectedSlotCycleAnimation = false; // probably not gonna use, but can enable | |||
| 280 | CustomColors_t hudColors; | |||
| 281 | EnemyBarSettings_t enemyBarSettings; | |||
| 282 | #ifdef BARONY_SUPER_MULTIPLAYER | |||
| 283 | StatusEffectQueue_t StatusEffectQueue[MAXPLAYERS4] = { {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7} }; | |||
| 284 | #else | |||
| 285 | StatusEffectQueue_t StatusEffectQueue[MAXPLAYERS4] = { {0}, {1}, {2}, {3} }; | |||
| 286 | #endif | |||
| 287 | std::unordered_map<int, StatusEffectQueue_t::EffectDefinitionEntry_t> StatusEffectQueue_t::StatusEffectDefinitions_t::allEffects; | |||
| 288 | std::unordered_map<int, StatusEffectQueue_t::EffectDefinitionEntry_t> StatusEffectQueue_t::StatusEffectDefinitions_t::allSustainedSpells; | |||
| 289 | Uint32 StatusEffectQueue_t::StatusEffectDefinitions_t::tooltipDescColor = 0xFFFFFFFF; | |||
| 290 | Uint32 StatusEffectQueue_t::StatusEffectDefinitions_t::tooltipHeadingColor = 0xFFFFFFFF; | |||
| 291 | Uint32 StatusEffectQueue_t::StatusEffectDefinitions_t::notificationTextColor = 0xFFFFFFFF; | |||
| 292 | std::string StatusEffectQueue_t::StatusEffectDefinitions_t::notificationFont = "fonts/pixelmix.ttf#16#2"; | |||
| 293 | ||||
| 294 | std::string formatSkillSheetEffects(int playernum, int proficiency, std::string& tag, std::string& rawValue); | |||
| 295 | ||||
| 296 | int GAMEUI_FRAMEDATA_ANIMATING_ITEM = 1; | |||
| 297 | int GAMEUI_FRAMEDATA_ALCHEMY_ITEM = 2; | |||
| 298 | int GAMEUI_FRAMEDATA_ALCHEMY_RECIPE_SLOT = 3; | |||
| 299 | int GAMEUI_FRAMEDATA_ALCHEMY_RECIPE_ENTRY = 4; | |||
| 300 | int GAMEUI_FRAMEDATA_WORLDTOOLTIP_ITEM = 5; | |||
| 301 | int GAMEUI_FRAMEDATA_SHOP_ITEM = 6; | |||
| 302 | ||||
| 303 | MinotaurWarning_t minotaurWarning[MAXPLAYERS4]; | |||
| 304 | ||||
| 305 | void updateLevelUpFrame(const int player); | |||
| 306 | void updateSkillUpFrame(const int player); | |||
| 307 | void drawClockwiseSquareMesh(const char* texture, float lerp, SDL_Rect rect, Uint32 color); | |||
| 308 | ||||
| 309 | void capitalizeString(std::string& str) | |||
| 310 | { | |||
| 311 | if ( str.size() < 1 ) { return; } | |||
| 312 | char letter = str[0]; | |||
| 313 | if ( letter >= 'a' && letter <= 'z' ) | |||
| 314 | { | |||
| 315 | str[0] = toupper(letter); | |||
| 316 | } | |||
| 317 | } | |||
| 318 | ||||
| 319 | void uppercaseString(std::string& str) | |||
| 320 | { | |||
| 321 | if ( str.size() < 1 ) { return; } | |||
| 322 | for ( auto& letter : str ) | |||
| 323 | { | |||
| 324 | if ( letter >= 'a' && letter <= 'z' ) | |||
| 325 | { | |||
| 326 | letter = toupper(letter); | |||
| 327 | } | |||
| 328 | } | |||
| 329 | } | |||
| 330 | ||||
| 331 | void camelCaseString(std::string& str) | |||
| 332 | { | |||
| 333 | if ( str.size() < 1 ) { return; } | |||
| 334 | char prevLetter = ' '; | |||
| 335 | for ( auto& letter : str ) | |||
| 336 | { | |||
| 337 | if ( letter >= 'a' && letter <= 'z' && prevLetter == ' ' ) | |||
| 338 | { | |||
| 339 | letter = toupper(letter); | |||
| 340 | } | |||
| 341 | prevLetter = letter; | |||
| 342 | } | |||
| 343 | } | |||
| 344 | ||||
| 345 | bool stringStartsWithVowel(std::string& str) | |||
| 346 | { | |||
| 347 | if ( str.size() < 1 ) { return false; } | |||
| 348 | switch ( str[0] ) | |||
| 349 | { | |||
| 350 | case 'a': | |||
| 351 | case 'e': | |||
| 352 | case 'i': | |||
| 353 | case 'o': | |||
| 354 | case 'u': | |||
| 355 | case 'A': | |||
| 356 | case 'E': | |||
| 357 | case 'I': | |||
| 358 | case 'O': | |||
| 359 | case 'U': | |||
| 360 | return true; | |||
| 361 | default: | |||
| 362 | break; | |||
| 363 | } | |||
| 364 | return false; | |||
| 365 | } | |||
| 366 | ||||
| 367 | std::string EnemyBarSettings_t::getEnemyBarSpriteName(Entity* entity) | |||
| 368 | { | |||
| 369 | if ( !entity ) { return "default"; } | |||
| 370 | ||||
| 371 | if ( entity->behavior == &actPlayer || entity->behavior == &actMonster ) | |||
| 372 | { | |||
| 373 | int type = entity->getMonsterTypeFromSprite(); | |||
| 374 | if ( type < NUMMONSTERS && type >= 0 ) | |||
| 375 | { | |||
| 376 | if ( type == MIMIC ) | |||
| 377 | { | |||
| 378 | if ( entity->isInertMimic() ) | |||
| 379 | { | |||
| 380 | return "chest_mimic"; | |||
| 381 | } | |||
| 382 | } | |||
| 383 | return monstertypename[type]; | |||
| 384 | } | |||
| 385 | } | |||
| 386 | else if ( entity->behavior == &actDoor ) | |||
| 387 | { | |||
| 388 | return "door"; | |||
| 389 | } | |||
| 390 | else if ( entity->behavior == &actChest ) | |||
| 391 | { | |||
| 392 | return "chest"; | |||
| 393 | } | |||
| 394 | else if ( entity->isDamageableCollider() ) | |||
| 395 | { | |||
| 396 | auto& colliderData = EditorEntityData_t::colliderData[entity->colliderDamageTypes]; | |||
| 397 | return colliderData.hpbarLookupName; | |||
| 398 | } | |||
| 399 | else if ( entity->behavior == &actFurniture ) | |||
| 400 | { | |||
| 401 | switch ( entity->furnitureType ) | |||
| 402 | { | |||
| 403 | case FURNITURE_TABLE: | |||
| 404 | case FURNITURE_PODIUM: | |||
| 405 | return "table"; | |||
| 406 | break; | |||
| 407 | default: | |||
| 408 | return "chair"; | |||
| 409 | break; | |||
| 410 | } | |||
| 411 | } | |||
| 412 | return "default"; | |||
| 413 | } | |||
| 414 | ||||
| 415 | enum ImageIndexes9x9 : int | |||
| 416 | { | |||
| 417 | TOP_LEFT, | |||
| 418 | TOP_RIGHT, | |||
| 419 | TOP, | |||
| 420 | MIDDLE_LEFT, | |||
| 421 | MIDDLE_RIGHT, | |||
| 422 | MIDDLE, | |||
| 423 | BOTTOM_LEFT, | |||
| 424 | BOTTOM_RIGHT, | |||
| 425 | BOTTOM | |||
| 426 | }; | |||
| 427 | ||||
| 428 | const std::vector<std::string> skillsheetEffectBackgroundImages = | |||
| 429 | { | |||
| 430 | "9x9 bg top left", | |||
| 431 | "9x9 bg top right", | |||
| 432 | "9x9 bg top middle", | |||
| 433 | "9x9 bg left", | |||
| 434 | "9x9 bg right", | |||
| 435 | "9x9 bg middle", | |||
| 436 | "9x9 bg bottom left", | |||
| 437 | "9x9 bg bottom right", | |||
| 438 | "9x9 bg bottom middle" | |||
| 439 | }; | |||
| 440 | ||||
| 441 | void imageSetWidthHeight9x9(Frame* container, const std::vector<std::string>& imgNames) | |||
| 442 | { | |||
| 443 | for ( auto& img : imgNames ) | |||
| 444 | { | |||
| 445 | if ( auto i = container->findImage(img.c_str()) ) | |||
| 446 | { | |||
| 447 | if ( auto imgGet = Image::get(i->path.c_str()) ) | |||
| 448 | { | |||
| 449 | i->pos.w = (int)imgGet->getWidth(); | |||
| 450 | i->pos.h = (int)imgGet->getHeight(); | |||
| 451 | } | |||
| 452 | } | |||
| 453 | } | |||
| 454 | } | |||
| 455 | ||||
| 456 | // for 9x9 images stretched to fit a container | |||
| 457 | void imageResizeToContainer9x9(Frame* container, SDL_Rect dimensionsToFill, const std::vector<std::string>& imgNames) | |||
| 458 | { | |||
| 459 | assert(imgNames.size() == 9)(static_cast<void> (0)); | |||
| 460 | // adjust inner background image elements | |||
| 461 | auto tl = container->findImage(imgNames[TOP_LEFT].c_str()); | |||
| 462 | tl->pos.x = dimensionsToFill.x; | |||
| 463 | tl->pos.y = dimensionsToFill.y; | |||
| 464 | auto tr = container->findImage(imgNames[TOP_RIGHT].c_str()); | |||
| 465 | tr->pos.x = dimensionsToFill.w - tr->pos.w; | |||
| 466 | tr->pos.y = dimensionsToFill.y; | |||
| 467 | auto tm = container->findImage(imgNames[TOP].c_str()); | |||
| 468 | tm->pos.x = tl->pos.x + tl->pos.w; | |||
| 469 | tm->pos.y = dimensionsToFill.y; | |||
| 470 | tm->pos.w = dimensionsToFill.w - tr->pos.w - tl->pos.w; | |||
| 471 | auto bl = container->findImage(imgNames[BOTTOM_LEFT].c_str()); | |||
| 472 | bl->pos.x = dimensionsToFill.x; | |||
| 473 | bl->pos.y = dimensionsToFill.h - bl->pos.h; | |||
| 474 | auto br = container->findImage(imgNames[BOTTOM_RIGHT].c_str()); | |||
| 475 | br->pos.x = dimensionsToFill.w - br->pos.w; | |||
| 476 | br->pos.y = bl->pos.y; | |||
| 477 | auto bm = container->findImage(imgNames[BOTTOM].c_str()); | |||
| 478 | bm->pos.x = bl->pos.x + bl->pos.w; | |||
| 479 | bm->pos.w = dimensionsToFill.w - bl->pos.w - br->pos.w; | |||
| 480 | bm->pos.y = bl->pos.y; | |||
| 481 | auto ml = container->findImage(imgNames[MIDDLE_LEFT].c_str()); | |||
| 482 | ml->pos.x = dimensionsToFill.x; | |||
| 483 | ml->pos.y = tl->pos.y + tl->pos.h; | |||
| 484 | ml->pos.h = dimensionsToFill.h - dimensionsToFill.y - bl->pos.h - tl->pos.h; | |||
| 485 | auto mr = container->findImage(imgNames[MIDDLE_RIGHT].c_str()); | |||
| 486 | mr->pos.x = dimensionsToFill.w - mr->pos.w; | |||
| 487 | mr->pos.y = ml->pos.y; | |||
| 488 | mr->pos.h = ml->pos.h; | |||
| 489 | auto mm = container->findImage(imgNames[MIDDLE].c_str()); | |||
| 490 | mm->pos.x = ml->pos.x + ml->pos.w; | |||
| 491 | mm->pos.y = ml->pos.y; | |||
| 492 | mm->pos.w = dimensionsToFill.w - ml->pos.w - mr->pos.w; | |||
| 493 | mm->pos.h = ml->pos.h; | |||
| 494 | } | |||
| 495 | ||||
| 496 | static ConsoleVariable<bool> cvar_mp_flash_whole_bar("/mp_flash_whole_bar", true); | |||
| 497 | struct MPBarPaths_t | |||
| 498 | { | |||
| 499 | static const std::map<std::string, std::string> normalMPBars; | |||
| 500 | static const std::map<std::string, std::string> automatonHTBars; | |||
| 501 | static const std::map<std::string, std::string> automatonSTBars; | |||
| 502 | static const std::map<std::string, std::string> insectoidENBars; | |||
| 503 | static const std::map<std::string, std::string> warningMPBars; | |||
| 504 | static const std::map<std::string, std::string>& getMPBar(const int player) | |||
| 505 | { | |||
| 506 | /*if ( keystatus[SDLK_h] ) | |||
| 507 | { | |||
| 508 | return automatonHTBars; | |||
| 509 | }*/ | |||
| 510 | if ( stats[player]->type == AUTOMATON ) | |||
| 511 | { | |||
| 512 | /*if ( keystatus[SDLK_g] ) | |||
| 513 | { | |||
| 514 | return automatonHTBars; | |||
| 515 | }*/ | |||
| 516 | return automatonSTBars; | |||
| 517 | } | |||
| 518 | else if ( stats[player]->playerRace == RACE_INSECTOID && stats[player]->appearance == 0 ) | |||
| 519 | { | |||
| 520 | return insectoidENBars; | |||
| 521 | } | |||
| 522 | return normalMPBars; | |||
| 523 | } | |||
| 524 | static const std::string& get(const int player, const std::string key) | |||
| 525 | { | |||
| 526 | if ( (players[player]->magic.noManaProcessedOnTick != 0 | |||
| 527 | && players[player]->magic.noManaFeedbackTicks % 20 < 10) ) | |||
| 528 | { | |||
| 529 | if ( *cvar_mp_flash_whole_bar ) | |||
| 530 | { | |||
| 531 | if ( key.find("fade") == std::string::npos ) | |||
| 532 | { | |||
| 533 | return warningMPBars.at(key); | |||
| 534 | } | |||
| 535 | } | |||
| 536 | else | |||
| 537 | { | |||
| 538 | if ( key == "mp img value" ) | |||
| 539 | { | |||
| 540 | return warningMPBars.at(key); | |||
| 541 | } | |||
| 542 | } | |||
| 543 | } | |||
| 544 | return getMPBar(player).at(key); | |||
| 545 | } | |||
| 546 | }; | |||
| 547 | ||||
| 548 | const std::map<std::string, std::string> MPBarPaths_t::normalMPBars = { | |||
| 549 | { "mp img progress bot", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPBot_00.png" }, | |||
| 550 | { "mp img progress bot 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPBot_01.png" }, | |||
| 551 | { "mp img progress bot 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPBot_02.png" }, | |||
| 552 | { "mp img progress bot 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPBot_03.png" }, | |||
| 553 | ||||
| 554 | { "mp img progress endcap","*#images/ui/HUD/hpmpbars/HUD_Bars_MPEnd_00.png" }, | |||
| 555 | { "mp img progress endcap 1","*#images/ui/HUD/hpmpbars/HUD_Bars_MPEnd_01.png" }, | |||
| 556 | ||||
| 557 | { "mp img progress endcap flash", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPEnd_F00.png" }, | |||
| 558 | { "mp img progress endcap flash 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPEnd_F01.png" }, | |||
| 559 | { "mp img progress endcap flash 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPEnd_F02.png" }, | |||
| 560 | { "mp img progress endcap flash 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPEnd_F03.png" }, | |||
| 561 | { "mp img progress endcap flash 4", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPEnd_F04.png" }, | |||
| 562 | { "mp img progress endcap flash b", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPEnd_F00b.png" }, | |||
| 563 | { "mp img progress endcap flash c", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPEnd_F00c.png" }, | |||
| 564 | { "mp img progress endcap flash d", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPEnd_F00d.png" }, | |||
| 565 | ||||
| 566 | { "mp img fade endcap", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPEndFade_00.png" }, | |||
| 567 | ||||
| 568 | { "mp img progress", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPMid_00.png" }, | |||
| 569 | { "mp img progress 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPMid_01.png" }, | |||
| 570 | { "mp img progress 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPMid_02.png" }, | |||
| 571 | { "mp img progress 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPMid_03.png" }, | |||
| 572 | ||||
| 573 | { "mp img fade bot", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPMidFade_00.png" }, | |||
| 574 | { "mp img fade", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPMidFade_00.png" }, | |||
| 575 | ||||
| 576 | { "mp img value", "*#images/ui/HUD/hpmpbars/HUD_Bars_MPNumBase_00.png" } | |||
| 577 | }; | |||
| 578 | ||||
| 579 | const std::map<std::string, std::string> MPBarPaths_t::automatonHTBars = { | |||
| 580 | { "mp img progress bot", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTBot_00.png" }, | |||
| 581 | { "mp img progress bot 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTBot_01.png" }, | |||
| 582 | { "mp img progress bot 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTBot_02.png" }, | |||
| 583 | { "mp img progress bot 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTBot_03.png" }, | |||
| 584 | ||||
| 585 | { "mp img progress endcap","*#images/ui/HUD/hpmpbars/HUD_Bars_HTEnd_00.png" }, | |||
| 586 | { "mp img progress endcap 1","*#images/ui/HUD/hpmpbars/HUD_Bars_HTEnd_01.png" }, | |||
| 587 | ||||
| 588 | { "mp img progress endcap flash", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTEnd_F00.png" }, | |||
| 589 | { "mp img progress endcap flash 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTEnd_F01.png" }, | |||
| 590 | { "mp img progress endcap flash 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTEnd_F02.png" }, | |||
| 591 | { "mp img progress endcap flash 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTEnd_F03.png" }, | |||
| 592 | { "mp img progress endcap flash 4", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTEnd_F04.png" }, | |||
| 593 | { "mp img progress endcap flash b", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTEnd_F00b.png" }, | |||
| 594 | { "mp img progress endcap flash c", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTEnd_F00c.png" }, | |||
| 595 | { "mp img progress endcap flash d", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTEnd_F00d.png" }, | |||
| 596 | ||||
| 597 | { "mp img fade endcap", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTEndFade_00.png" }, | |||
| 598 | ||||
| 599 | { "mp img progress", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTMid_00.png" }, | |||
| 600 | { "mp img progress 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTMid_01.png" }, | |||
| 601 | { "mp img progress 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTMid_02.png" }, | |||
| 602 | { "mp img progress 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTMid_03.png" }, | |||
| 603 | ||||
| 604 | { "mp img fade bot", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTMidFade_00.png" }, | |||
| 605 | { "mp img fade", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTMidFade_00.png" }, | |||
| 606 | ||||
| 607 | { "mp img value", "*#images/ui/HUD/hpmpbars/HUD_Bars_HTNumBase_00.png" } | |||
| 608 | }; | |||
| 609 | ||||
| 610 | const std::map<std::string, std::string> MPBarPaths_t::automatonSTBars = { | |||
| 611 | { "mp img progress bot", "*#images/ui/HUD/hpmpbars/HUD_Bars_STBot_00.png" }, | |||
| 612 | { "mp img progress bot 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_STBot_01.png" }, | |||
| 613 | { "mp img progress bot 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_STBot_02.png" }, | |||
| 614 | { "mp img progress bot 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_STBot_03.png" }, | |||
| 615 | ||||
| 616 | { "mp img progress endcap","*#images/ui/HUD/hpmpbars/HUD_Bars_STEnd_00.png" }, | |||
| 617 | { "mp img progress endcap 1","*#images/ui/HUD/hpmpbars/HUD_Bars_STEnd_01.png" }, | |||
| 618 | ||||
| 619 | { "mp img progress endcap flash", "*#images/ui/HUD/hpmpbars/HUD_Bars_STEnd_F00.png" }, | |||
| 620 | { "mp img progress endcap flash 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_STEnd_F01.png" }, | |||
| 621 | { "mp img progress endcap flash 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_STEnd_F02.png" }, | |||
| 622 | { "mp img progress endcap flash 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_STEnd_F03.png" }, | |||
| 623 | { "mp img progress endcap flash 4", "*#images/ui/HUD/hpmpbars/HUD_Bars_STEnd_F04.png" }, | |||
| 624 | { "mp img progress endcap flash b", "*#images/ui/HUD/hpmpbars/HUD_Bars_STEnd_F00b.png" }, | |||
| 625 | { "mp img progress endcap flash c", "*#images/ui/HUD/hpmpbars/HUD_Bars_STEnd_F00c.png" }, | |||
| 626 | { "mp img progress endcap flash d", "*#images/ui/HUD/hpmpbars/HUD_Bars_STEnd_F00d.png" }, | |||
| 627 | ||||
| 628 | { "mp img fade endcap", "*#images/ui/HUD/hpmpbars/HUD_Bars_STEndFade_00.png" }, | |||
| 629 | ||||
| 630 | { "mp img progress", "*#images/ui/HUD/hpmpbars/HUD_Bars_STMid_00.png" }, | |||
| 631 | { "mp img progress 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_STMid_01.png" }, | |||
| 632 | { "mp img progress 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_STMid_02.png" }, | |||
| 633 | { "mp img progress 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_STMid_03.png" }, | |||
| 634 | ||||
| 635 | { "mp img fade bot", "*#images/ui/HUD/hpmpbars/HUD_Bars_STMidFade_00.png" }, | |||
| 636 | { "mp img fade", "*#images/ui/HUD/hpmpbars/HUD_Bars_STMidFade_00.png" }, | |||
| 637 | ||||
| 638 | { "mp img value", "*#images/ui/HUD/hpmpbars/HUD_Bars_STNumBase_00.png" } | |||
| 639 | }; | |||
| 640 | ||||
| 641 | const std::map<std::string, std::string> MPBarPaths_t::insectoidENBars = { | |||
| 642 | { "mp img progress bot", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENBot_00.png" }, | |||
| 643 | { "mp img progress bot 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENBot_01.png" }, | |||
| 644 | { "mp img progress bot 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENBot_02.png" }, | |||
| 645 | { "mp img progress bot 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENBot_03.png" }, | |||
| 646 | ||||
| 647 | { "mp img progress endcap","*#images/ui/HUD/hpmpbars/HUD_Bars_ENEnd_00.png" }, | |||
| 648 | { "mp img progress endcap 1","*#images/ui/HUD/hpmpbars/HUD_Bars_ENEnd_01.png" }, | |||
| 649 | ||||
| 650 | { "mp img progress endcap flash", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENEnd_F00.png" }, | |||
| 651 | { "mp img progress endcap flash 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENEnd_F01.png" }, | |||
| 652 | { "mp img progress endcap flash 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENEnd_F02.png" }, | |||
| 653 | { "mp img progress endcap flash 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENEnd_F03.png" }, | |||
| 654 | { "mp img progress endcap flash 4", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENEnd_F04.png" }, | |||
| 655 | { "mp img progress endcap flash b", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENEnd_F00b.png" }, | |||
| 656 | { "mp img progress endcap flash c", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENEnd_F00c.png" }, | |||
| 657 | { "mp img progress endcap flash d", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENEnd_F00d.png" }, | |||
| 658 | ||||
| 659 | { "mp img fade endcap", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENEndFade_00.png" }, | |||
| 660 | ||||
| 661 | { "mp img progress", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENMid_00.png" }, | |||
| 662 | { "mp img progress 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENMid_01.png" }, | |||
| 663 | { "mp img progress 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENMid_02.png" }, | |||
| 664 | { "mp img progress 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENMid_03.png" }, | |||
| 665 | ||||
| 666 | { "mp img fade bot", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENMidFade_00.png" }, | |||
| 667 | { "mp img fade", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENMidFade_00.png" }, | |||
| 668 | ||||
| 669 | { "mp img value", "*#images/ui/HUD/hpmpbars/HUD_Bars_ENNumBase_00.png" } | |||
| 670 | }; | |||
| 671 | ||||
| 672 | const std::map<std::string, std::string> MPBarPaths_t::warningMPBars = { | |||
| 673 | { "mp img progress bot", "*#images/ui/HUD/hpmpbars/HUD_Bars_NABot_00.png" }, | |||
| 674 | { "mp img progress bot 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_NABot_01.png" }, | |||
| 675 | { "mp img progress bot 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_NABot_02.png" }, | |||
| 676 | { "mp img progress bot 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_NABot_03.png" }, | |||
| 677 | ||||
| 678 | { "mp img progress endcap","*#images/ui/HUD/hpmpbars/HUD_Bars_NAEnd_00.png" }, | |||
| 679 | { "mp img progress endcap 1","*#images/ui/HUD/hpmpbars/HUD_Bars_NAEnd_01.png" }, | |||
| 680 | ||||
| 681 | { "mp img progress endcap flash", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAEnd_F00.png" }, | |||
| 682 | { "mp img progress endcap flash 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAEnd_F01.png" }, | |||
| 683 | { "mp img progress endcap flash 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAEnd_F02.png" }, | |||
| 684 | { "mp img progress endcap flash 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAEnd_F03.png" }, | |||
| 685 | { "mp img progress endcap flash 4", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAEnd_F04.png" }, | |||
| 686 | { "mp img progress endcap flash b", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAEnd_F00b.png" }, | |||
| 687 | { "mp img progress endcap flash c", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAEnd_F00c.png" }, | |||
| 688 | { "mp img progress endcap flash d", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAEnd_F00d.png" }, | |||
| 689 | ||||
| 690 | { "mp img fade endcap", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAEndFade_00.png" }, | |||
| 691 | ||||
| 692 | { "mp img progress", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAMid_00.png" }, | |||
| 693 | { "mp img progress 1", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAMid_01.png" }, | |||
| 694 | { "mp img progress 2", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAMid_02.png" }, | |||
| 695 | { "mp img progress 3", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAMid_03.png" }, | |||
| 696 | ||||
| 697 | { "mp img fade bot", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAMidFade_00.png" }, | |||
| 698 | { "mp img fade", "*#images/ui/HUD/hpmpbars/HUD_Bars_NAMidFade_00.png" }, | |||
| 699 | ||||
| 700 | { "mp img value", "*#images/ui/HUD/hpmpbars/HUD_Bars_NANumBase_00.png" } | |||
| 701 | }; | |||
| 702 | ||||
| 703 | void createHPMPBars(const int player) | |||
| 704 | { | |||
| 705 | auto& hud_t = players[player]->hud; | |||
| 706 | const int barTotalHeight = hud_t.HPMP_FRAME_HEIGHT; | |||
| 707 | const int hpBarStartY = (hud_t.hudFrame->getSize().h - hud_t.HPMP_FRAME_START_Y); | |||
| 708 | const int mpBarStartY = hpBarStartY + barTotalHeight; | |||
| 709 | const int barWidth = hud_t.HPMP_FRAME_WIDTH; | |||
| 710 | const int barStartX = hud_t.HPMP_FRAME_START_X; | |||
| 711 | { | |||
| 712 | hud_t.hpFrame = hud_t.hudFrame->addFrame("hp bar"); | |||
| 713 | hud_t.hpFrame->setHollow(true); | |||
| 714 | ||||
| 715 | SDL_Rect pos{ barStartX, hpBarStartY, barWidth, barTotalHeight }; | |||
| 716 | hud_t.hpFrame->setSize(pos); | |||
| 717 | ||||
| 718 | auto fadeFrame = hud_t.hpFrame->addFrame("hp fade frame"); | |||
| 719 | fadeFrame->setSize(SDL_Rect{0, 0, barWidth, barTotalHeight}); | |||
| 720 | fadeFrame->setInheritParentFrameOpacity(false); | |||
| 721 | ||||
| 722 | auto foregroundFrame = hud_t.hpFrame->addFrame("hp foreground frame"); | |||
| 723 | foregroundFrame->setSize(SDL_Rect{ 0, 0, barWidth, barTotalHeight }); | |||
| 724 | ||||
| 725 | ||||
| 726 | auto base = hud_t.hpFrame->addImage(SDL_Rect{ 54, 4, barWidth - 54, 26 }, 0xFFFFFFFF, | |||
| 727 | "*#images/ui/HUD/hpmpbars/HUD_Bars_Base_00.png", "hp img base"); | |||
| 728 | ||||
| 729 | const int progressBarHeight = 22; | |||
| 730 | auto fadeProgressBase = fadeFrame->addImage(SDL_Rect{ 54, 6, 6, progressBarHeight }, 0xFFFFFFFF, | |||
| 731 | "*#images/ui/HUD/hpmpbars/HUD_Bars_HPMidFade_00.png", "hp img fade bot"); | |||
| 732 | auto fadeProgress = fadeFrame->addImage(SDL_Rect{ 60, 6, barWidth - 60 - 8, progressBarHeight }, 0xFFFFFFFF, | |||
| 733 | "*#images/ui/HUD/hpmpbars/HUD_Bars_HPMidFade_00.png", "hp img fade"); | |||
| 734 | auto fadeProgressEndCap = fadeFrame->addImage(SDL_Rect{ | |||
| 735 | fadeProgress->pos.x + fadeProgress->pos.w, 6, 8, progressBarHeight }, 0xFFFFFFFF, | |||
| 736 | "*#images/ui/HUD/hpmpbars/HUD_Bars_HPEndFade_00.png", "hp img fade endcap"); | |||
| 737 | ||||
| 738 | auto numbase = foregroundFrame->addImage(SDL_Rect{ 0, 4, 48, 26 }, 0xFFFFFFFF, | |||
| 739 | "*#images/ui/HUD/hpmpbars/HUD_Bars_HPNumBase_00.png", "hp img value"); | |||
| 740 | auto div = foregroundFrame->addImage(SDL_Rect{ 46, 0, 8, 34 }, 0xFFFFFFFF, | |||
| 741 | "*#images/ui/HUD/hpmpbars/HUD_Bars_Separator_00.png", "hp img div"); | |||
| 742 | ||||
| 743 | auto currentProgressBase = foregroundFrame->addImage(SDL_Rect{ 54, 6, 6, progressBarHeight }, 0xFFFFFFFF, | |||
| 744 | "*#images/ui/HUD/hpmpbars/HUD_Bars_HPBot_00.png", "hp img progress bot"); | |||
| 745 | auto currentProgress = foregroundFrame->addImage(SDL_Rect{ 60, 6, barWidth - 60 - 8, progressBarHeight }, 0xFFFFFFFF, | |||
| 746 | "*#images/ui/HUD/hpmpbars/HUD_Bars_HPMid_00.png", "hp img progress"); | |||
| 747 | auto currentProgressEndCap = foregroundFrame->addImage(SDL_Rect{ | |||
| 748 | currentProgress->pos.x + currentProgress->pos.w, 6, 8, progressBarHeight }, 0xFFFFFFFF, | |||
| 749 | "*#images/ui/HUD/hpmpbars/HUD_Bars_HPEnd_00.png", "hp img progress endcap"); | |||
| 750 | auto currentProgressEndCapFlash = foregroundFrame->addImage(SDL_Rect{ | |||
| 751 | currentProgress->pos.x + currentProgress->pos.w - 14, 6, 22, progressBarHeight }, 0xFFFFFFFF, | |||
| 752 | "*#images/ui/HUD/hpmpbars/HUD_Bars_HPEnd_F00.png", "hp img progress endcap flash"); | |||
| 753 | currentProgressEndCapFlash->disabled = true; | |||
| 754 | ||||
| 755 | const int endCapWidth = 16; | |||
| 756 | auto endCap = foregroundFrame->addImage(SDL_Rect{ pos.w - endCapWidth, 0, endCapWidth, barTotalHeight }, 0xFFFFFFFF, | |||
| 757 | "*#images/ui/HUD/hpmpbars/HUD_Bars_EndCap_00.png", "hp img endcap"); | |||
| 758 | ||||
| 759 | auto div25Percent = foregroundFrame->addImage(SDL_Rect{ 0, 8, 2, 18 }, 0xFFFFFFFF, | |||
| 760 | "*#images/ui/HUD/hpmpbars/HUD_Bars_Divider_01.png", "hp img div 25pc"); | |||
| 761 | div25Percent->disabled = true; | |||
| 762 | auto div50Percent = foregroundFrame->addImage(SDL_Rect{ 0, 8, 2, 18 }, 0xFFFFFFFF, | |||
| 763 | "*#images/ui/HUD/hpmpbars/HUD_Bars_Divider_01.png", "hp img div 50pc"); | |||
| 764 | div50Percent->disabled = true; | |||
| 765 | auto div75Percent = foregroundFrame->addImage(SDL_Rect{ 0, 8, 2, 18 }, 0xFFFFFFFF, | |||
| 766 | "*#images/ui/HUD/hpmpbars/HUD_Bars_Divider_01.png", "hp img div 75pc"); | |||
| 767 | div75Percent->disabled = true; | |||
| 768 | ||||
| 769 | auto font = "fonts/pixel_maz.ttf#32#2"; | |||
| 770 | auto hptext = foregroundFrame->addField("hp text", 16); | |||
| 771 | hptext->setText("0"); | |||
| 772 | hptext->setSize(numbase->pos); | |||
| 773 | hptext->setFont(font); | |||
| 774 | hptext->setVJustify(Field::justify_t::CENTER); | |||
| 775 | hptext->setHJustify(Field::justify_t::CENTER); | |||
| 776 | hptext->setColor(makeColor( 255, 255, 255, 255)); | |||
| 777 | } | |||
| 778 | ||||
| 779 | // MP bar below | |||
| 780 | { | |||
| 781 | hud_t.mpFrame = hud_t.hudFrame->addFrame("mp bar"); | |||
| 782 | hud_t.mpFrame->setHollow(true); | |||
| 783 | ||||
| 784 | SDL_Rect pos{ barStartX, mpBarStartY, barWidth, barTotalHeight }; | |||
| 785 | hud_t.mpFrame->setSize(pos); | |||
| 786 | ||||
| 787 | auto fadeFrame = hud_t.mpFrame->addFrame("mp fade frame"); | |||
| 788 | fadeFrame->setSize(SDL_Rect{ 0, 0, barWidth, barTotalHeight }); | |||
| 789 | fadeFrame->setInheritParentFrameOpacity(false); | |||
| 790 | ||||
| 791 | auto foregroundFrame = hud_t.mpFrame->addFrame("mp foreground frame"); | |||
| 792 | foregroundFrame->setSize(SDL_Rect{ 0, 0, barWidth, barTotalHeight }); | |||
| 793 | ||||
| 794 | ||||
| 795 | auto base = hud_t.mpFrame->addImage(SDL_Rect{ 54, 4, barWidth - 54, 26 }, 0xFFFFFFFF, | |||
| 796 | "*#images/ui/HUD/hpmpbars/HUD_Bars_Base_00.png", "mp img base"); | |||
| 797 | ||||
| 798 | const int progressBarHeight = 22; | |||
| 799 | auto fadeProgressBase = fadeFrame->addImage(SDL_Rect{ 54, 6, 6, progressBarHeight }, 0xFFFFFFFF, | |||
| 800 | "*#images/ui/HUD/hpmpbars/HUD_Bars_MPMidFade_00.png", "mp img fade bot"); | |||
| 801 | auto fadeProgress = fadeFrame->addImage(SDL_Rect{ 60, 6, barWidth - 60 - 8, progressBarHeight }, 0xFFFFFFFF, | |||
| 802 | "*#images/ui/HUD/hpmpbars/HUD_Bars_MPMidFade_00.png", "mp img fade"); | |||
| 803 | auto fadeProgressEndCap = fadeFrame->addImage(SDL_Rect{ | |||
| 804 | fadeProgress->pos.x + fadeProgress->pos.w, 6, 8, progressBarHeight }, 0xFFFFFFFF, | |||
| 805 | "*#images/ui/HUD/hpmpbars/HUD_Bars_MPEndFade_00.png", "mp img fade endcap"); | |||
| 806 | ||||
| 807 | auto numbase = foregroundFrame->addImage(SDL_Rect{ 0, 4, 48, 26 }, 0xFFFFFFFF, | |||
| 808 | "*#images/ui/HUD/hpmpbars/HUD_Bars_MPNumBase_00.png", "mp img value"); | |||
| 809 | auto div = foregroundFrame->addImage(SDL_Rect{ 46, 0, 8, 34 }, 0xFFFFFFFF, | |||
| 810 | "*#images/ui/HUD/hpmpbars/HUD_Bars_Separator_00.png", "mp img div"); | |||
| 811 | ||||
| 812 | auto currentProgressBase = foregroundFrame->addImage(SDL_Rect{ 54, 6, 6, progressBarHeight }, 0xFFFFFFFF, | |||
| 813 | "*#images/ui/HUD/hpmpbars/HUD_Bars_MPBot_00.png", "mp img progress bot"); | |||
| 814 | auto currentProgress = foregroundFrame->addImage(SDL_Rect{ 60, 6, barWidth - 60 - 8, progressBarHeight }, 0xFFFFFFFF, | |||
| 815 | "*#images/ui/HUD/hpmpbars/HUD_Bars_MPMid_00.png", "mp img progress"); | |||
| 816 | auto currentProgressEndCap = foregroundFrame->addImage(SDL_Rect{ | |||
| 817 | currentProgress->pos.x + currentProgress->pos.w, 6, 8, progressBarHeight }, 0xFFFFFFFF, | |||
| 818 | "*#images/ui/HUD/hpmpbars/HUD_Bars_MPEnd_00.png", "mp img progress endcap"); | |||
| 819 | auto currentProgressEndCapFlash = foregroundFrame->addImage(SDL_Rect{ | |||
| 820 | currentProgress->pos.x + currentProgress->pos.w - 14, 6, 22, progressBarHeight }, 0xFFFFFFFF, | |||
| 821 | "*#images/ui/HUD/hpmpbars/HUD_Bars_MPEnd_F00.png", "mp img progress endcap flash"); | |||
| 822 | currentProgressEndCapFlash->disabled = true; | |||
| 823 | ||||
| 824 | const int endCapWidth = 16; | |||
| 825 | auto endCap = foregroundFrame->addImage(SDL_Rect{ pos.w - endCapWidth, 0, endCapWidth, barTotalHeight }, 0xFFFFFFFF, | |||
| 826 | "*#images/ui/HUD/hpmpbars/HUD_Bars_EndCap_00.png", "mp img endcap"); | |||
| 827 | ||||
| 828 | auto div25Percent = foregroundFrame->addImage(SDL_Rect{ 0, 8, 2, 18 }, 0xFFFFFFFF, | |||
| 829 | "*#images/ui/HUD/hpmpbars/HUD_Bars_Divider_01.png", "mp img div 25pc"); | |||
| 830 | div25Percent->disabled = true; | |||
| 831 | auto div50Percent = foregroundFrame->addImage(SDL_Rect{ 0, 8, 2, 18 }, 0xFFFFFFFF, | |||
| 832 | "*#images/ui/HUD/hpmpbars/HUD_Bars_Divider_01.png", "mp img div 50pc"); | |||
| 833 | div50Percent->disabled = true; | |||
| 834 | auto div75Percent = foregroundFrame->addImage(SDL_Rect{ 0, 8, 2, 18 }, 0xFFFFFFFF, | |||
| 835 | "*#images/ui/HUD/hpmpbars/HUD_Bars_Divider_01.png", "mp img div 75pc"); | |||
| 836 | div75Percent->disabled = true; | |||
| 837 | ||||
| 838 | auto font = "fonts/pixel_maz.ttf#32#2"; | |||
| 839 | auto mptext = foregroundFrame->addField("mp text", 16); | |||
| 840 | mptext->setText("0"); | |||
| 841 | mptext->setSize(numbase->pos); | |||
| 842 | mptext->setFont(font); | |||
| 843 | mptext->setVJustify(Field::justify_t::CENTER); | |||
| 844 | mptext->setHJustify(Field::justify_t::CENTER); | |||
| 845 | mptext->setColor(makeColor( 255, 255, 255, 255)); | |||
| 846 | } | |||
| 847 | } | |||
| 848 | ||||
| 849 | void createAllyFollowerFrame(const int player) | |||
| 850 | { | |||
| 851 | auto& hud_t = players[player]->hud; | |||
| 852 | ||||
| 853 | auto frame = hud_t.hudFrame->addFrame("follower status"); | |||
| 854 | hud_t.allyFollowerFrame = frame; | |||
| 855 | frame->setHollow(true); | |||
| 856 | frame->setSize(SDL_Rect{ 0, 0, 300, 0 }); | |||
| 857 | frame->setDisabled(true); | |||
| 858 | frame->setScrollBarsEnabled(false); | |||
| 859 | frame->setAllowScrollBinds(false); | |||
| 860 | ||||
| 861 | auto selector = frame->addImage(SDL_Rect{ 0, 0, 8, 8 }, 0xFFFFFFFF, "*#images/ui/HUD/allies/HUD_Ally_Arrow_00.png", "selector"); | |||
| 862 | selector->disabled = true; | |||
| 863 | selector->ontop = true; | |||
| 864 | ||||
| 865 | auto glyphFrame = hud_t.hudFrame->addFrame("follower glyphs"); | |||
| 866 | hud_t.allyFollowerGlyphFrame = glyphFrame; | |||
| 867 | glyphFrame->setHollow(true); | |||
| 868 | glyphFrame->setSize(SDL_Rect{ 0, 0, 300, 0 }); | |||
| 869 | glyphFrame->setDisabled(true); | |||
| 870 | { | |||
| 871 | std::string font = "fonts/pixel_maz.ttf#32#2"; | |||
| 872 | /*auto commandText = glyphFrame->addField("command prompt txt", 32); | |||
| 873 | commandText->setFont(font.c_str()); | |||
| 874 | commandText->setHJustify(Field::justify_t::LEFT); | |||
| 875 | commandText->setVJustify(Field::justify_t::TOP); | |||
| 876 | commandText->setSize(SDL_Rect{ 0, 0, glyphFrame->getSize().w, 24 }); | |||
| 877 | commandText->setText(Language::get(4202)); | |||
| 878 | commandText->setColor(hudColors.characterSheetLightNeutral); | |||
| 879 | commandText->setOntop(true); | |||
| 880 | commandText->setDisabled(true);*/ | |||
| 881 | ||||
| 882 | auto glyphCommand = glyphFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "glyph command"); | |||
| 883 | glyphCommand->disabled = true; | |||
| 884 | glyphCommand->ontop = true; | |||
| 885 | ||||
| 886 | auto imgCommand = glyphFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, | |||
| 887 | "*#images/ui/HUD/allies/HUD_Ally_Circle_00.png", "img command"); | |||
| 888 | imgCommand->disabled = true; | |||
| 889 | imgCommand->ontop = true; | |||
| 890 | ||||
| 891 | /*auto repeatText = glyphFrame->addField("repeat prompt txt", 32); | |||
| 892 | repeatText->setFont(font.c_str()); | |||
| 893 | repeatText->setHJustify(Field::justify_t::LEFT); | |||
| 894 | repeatText->setVJustify(Field::justify_t::TOP); | |||
| 895 | repeatText->setSize(SDL_Rect{ 0, 0, frame->getSize().w, 24 }); | |||
| 896 | repeatText->setText(Language::get(4203)); | |||
| 897 | repeatText->setColor(hudColors.characterSheetLightNeutral); | |||
| 898 | repeatText->setOntop(true); | |||
| 899 | repeatText->setDisabled(true);*/ | |||
| 900 | ||||
| 901 | auto glyphRepeat = glyphFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "glyph repeat"); | |||
| 902 | glyphRepeat->disabled = true; | |||
| 903 | glyphRepeat->ontop = true; | |||
| 904 | ||||
| 905 | auto imgRepeat = glyphFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, | |||
| 906 | "*#images/ui/HUD/allies/HUD_Ally_Repeat_00.png", "img repeat"); | |||
| 907 | imgRepeat->disabled = true; | |||
| 908 | imgRepeat->ontop = true; | |||
| 909 | } | |||
| 910 | } | |||
| 911 | ||||
| 912 | void createCalloutPromptFrame(const int player) | |||
| 913 | { | |||
| 914 | auto& hud_t = players[player]->hud; | |||
| 915 | ||||
| 916 | auto frame = hud_t.hudFrame->addFrame("callout prompts"); | |||
| 917 | hud_t.calloutPromptFrame = frame; | |||
| 918 | frame->setHollow(true); | |||
| 919 | frame->setSize(SDL_Rect{ 0, 0, 300, 0 }); | |||
| 920 | frame->setDisabled(true); | |||
| 921 | frame->setScrollBarsEnabled(false); | |||
| 922 | frame->setAllowScrollBinds(false); | |||
| 923 | ||||
| 924 | auto glyph = frame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "glyph"); | |||
| 925 | glyph->disabled = true; | |||
| 926 | auto icon = frame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "icon"); | |||
| 927 | icon->disabled = true; | |||
| 928 | ||||
| 929 | auto text = frame->addField("prompt", 64); | |||
| 930 | text->setFont(smallfont_outline); | |||
| 931 | text->setHJustify(Field::justify_t::LEFT); | |||
| 932 | text->setVJustify(Field::justify_t::TOP); | |||
| 933 | text->setSize(SDL_Rect{ 0, 0, frame->getSize().w, 24 }); | |||
| 934 | text->setText(Language::get(6049)); | |||
| 935 | text->setColor(0xFFFFFFFF); | |||
| 936 | text->setOntop(true); | |||
| 937 | text->setDisabled(true); | |||
| 938 | } | |||
| 939 | ||||
| 940 | const int kPlayerBarsEntryFrameWidth = 214; | |||
| 941 | ||||
| 942 | void updateCalloutPromptFrame(const int player) | |||
| 943 | { | |||
| 944 | auto& hud_t = players[player]->hud; | |||
| 945 | auto frame = hud_t.calloutPromptFrame; | |||
| 946 | if ( !frame ) | |||
| 947 | { | |||
| 948 | return; | |||
| 949 | } | |||
| 950 | ||||
| 951 | if ( !CalloutRadialMenu::calloutMenuEnabledForGamemode() ) | |||
| 952 | { | |||
| 953 | frame->setDisabled(true); | |||
| 954 | return; | |||
| 955 | } | |||
| 956 | if ( !Player::getPlayerInteractEntity(player) ) | |||
| 957 | { | |||
| 958 | frame->setDisabled(true); | |||
| 959 | return; | |||
| 960 | } | |||
| 961 | if ( splitscreen && player == 3 ) | |||
| 962 | { | |||
| 963 | frame->setDisabled(true); // we overlap the minimap, so don't draw this one | |||
| 964 | return; | |||
| 965 | } | |||
| 966 | else if ( !players[player]->shootmode && !FollowerMenu[player].followerMenuIsOpen() | |||
| 967 | && !CalloutMenu[player].calloutMenuIsOpen() ) | |||
| 968 | { | |||
| 969 | frame->setDisabled(true); | |||
| 970 | return; | |||
| 971 | } | |||
| 972 | ||||
| 973 | int alignX = 8; | |||
| 974 | int alignY = 0; | |||
| 975 | static ConsoleVariable<bool> cvar_callout_prompt_horizontal("/callout_prompt_horizontal", false); | |||
| 976 | if ( hud_t.allyPlayerFrame && !hud_t.allyPlayerFrame->isDisabled() | |||
| 977 | && hud_t.allyPlayerFrame->getOpacity() > 0.0 ) | |||
| 978 | { | |||
| 979 | if ( hud_t.playerBars.size() > 0 ) | |||
| 980 | { | |||
| 981 | if ( *cvar_callout_prompt_horizontal ) | |||
| 982 | { | |||
| 983 | alignX += kPlayerBarsEntryFrameWidth; | |||
| 984 | } | |||
| 985 | else | |||
| 986 | { | |||
| 987 | alignY += hud_t.playerBars.size() * 36; | |||
| 988 | } | |||
| 989 | } | |||
| 990 | } | |||
| 991 | ||||
| 992 | frame->setDisabled(false); | |||
| 993 | SDL_Rect framePos; | |||
| 994 | framePos.x = alignX; | |||
| 995 | framePos.y = players[player]->bUseCompactGUIWidth() ? AllyStatusBarSettings_t::FollowerBars_t::entrySettings.baseYSplitscreen : AllyStatusBarSettings_t::FollowerBars_t::entrySettings.baseY; | |||
| 996 | framePos.y -= 4; | |||
| 997 | framePos.y += alignY; | |||
| 998 | framePos.w = 300; | |||
| 999 | framePos.h = 50; | |||
| 1000 | frame->setSize(framePos); | |||
| 1001 | ||||
| 1002 | auto glyph = frame->findImage("glyph"); | |||
| 1003 | auto glyphPathUnpressed = Input::inputs[player].getGlyphPathForBinding("Call Out", false); | |||
| 1004 | auto glyphPathPressed = Input::inputs[player].getGlyphPathForBinding("Call Out", true); | |||
| 1005 | glyph->disabled = true; | |||
| 1006 | ||||
| 1007 | const int nominalGlyphHeight = 26; | |||
| 1008 | int unpressedHeight = 0; | |||
| 1009 | int unpressedY = 0; | |||
| 1010 | if ( ticks % 50 < 25 && (CalloutMenu[player].calloutMenuIsOpen() && CalloutMenu[player].selectMoveTo) ) | |||
| 1011 | { | |||
| 1012 | glyph->path = glyphPathPressed; | |||
| 1013 | if ( auto imgGet = Image::get(glyph->path.c_str()) ) | |||
| 1014 | { | |||
| 1015 | glyph->disabled = false; | |||
| 1016 | SDL_Rect glyphPos{ 0, 8, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 1017 | glyph->pos = glyphPos; | |||
| 1018 | if ( auto imgGetUnpressed = Image::get(glyphPathUnpressed.c_str()) ) | |||
| 1019 | { | |||
| 1020 | unpressedHeight = imgGetUnpressed->getHeight(); | |||
| 1021 | unpressedY = glyph->pos.y; | |||
| 1022 | if ( unpressedHeight != glyph->pos.h ) | |||
| 1023 | { | |||
| 1024 | glyph->pos.y -= (glyph->pos.h - unpressedHeight); | |||
| 1025 | } | |||
| 1026 | ||||
| 1027 | if ( unpressedHeight != nominalGlyphHeight ) | |||
| 1028 | { | |||
| 1029 | unpressedY -= (unpressedHeight - nominalGlyphHeight) / 2; | |||
| 1030 | glyph->pos.y -= (unpressedHeight - nominalGlyphHeight) / 2; | |||
| 1031 | } | |||
| 1032 | } | |||
| 1033 | } | |||
| 1034 | } | |||
| 1035 | else | |||
| 1036 | { | |||
| 1037 | glyph->path = glyphPathUnpressed; | |||
| 1038 | if ( auto imgGet = Image::get(glyph->path.c_str()) ) | |||
| 1039 | { | |||
| 1040 | glyph->disabled = false; | |||
| 1041 | SDL_Rect glyphPos{ 0, 8, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 1042 | glyph->pos = glyphPos; | |||
| 1043 | unpressedHeight = glyph->pos.h; | |||
| 1044 | unpressedY = glyph->pos.y; | |||
| 1045 | if ( glyph->pos.h != nominalGlyphHeight ) | |||
| 1046 | { | |||
| 1047 | unpressedY -= (glyph->pos.h - nominalGlyphHeight) / 2; | |||
| 1048 | glyph->pos.y -= (glyph->pos.h - nominalGlyphHeight) / 2; | |||
| 1049 | } | |||
| 1050 | } | |||
| 1051 | } | |||
| 1052 | ||||
| 1053 | int glyphAlignY = unpressedY + (unpressedHeight - nominalGlyphHeight) / 2; | |||
| 1054 | ||||
| 1055 | auto icon = frame->findImage("icon"); | |||
| 1056 | icon->disabled = true; | |||
| 1057 | static ConsoleVariable<bool> cvar_callout_prompt_wheel("/callout_prompt_wheel", false); | |||
| 1058 | if ( !glyph->disabled ) | |||
| 1059 | { | |||
| 1060 | if ( *cvar_callout_prompt_wheel && | |||
| 1061 | CalloutMenu[player].calloutMenuIsOpen() && CalloutMenu[player].selectMoveTo ) | |||
| 1062 | { | |||
| 1063 | icon->path = "*images/ui/HUD/HUD_Ally_Callout_Wheel_00.png"; | |||
| 1064 | } | |||
| 1065 | else | |||
| 1066 | { | |||
| 1067 | icon->path = "*images/ui/HUD/HUD_Ally_Callout_00.png"; | |||
| 1068 | } | |||
| 1069 | if ( auto imgGet = Image::get(icon->path.c_str()) ) | |||
| 1070 | { | |||
| 1071 | icon->disabled = false; | |||
| 1072 | icon->pos.w = imgGet->getWidth(); | |||
| 1073 | icon->pos.h = imgGet->getHeight(); | |||
| 1074 | icon->pos.x = glyph->pos.x + glyph->pos.w + 4; | |||
| 1075 | icon->pos.y = unpressedY + (unpressedHeight) / 2 - icon->pos.h / 2; | |||
| 1076 | if ( icon->pos.y % 2 == 1 ) | |||
| 1077 | { | |||
| 1078 | ++icon->pos.y; | |||
| 1079 | } | |||
| 1080 | } | |||
| 1081 | } | |||
| 1082 | ||||
| 1083 | auto text = frame->findField("prompt"); | |||
| 1084 | text->setDisabled(true); | |||
| 1085 | static ConsoleVariable<bool> cvar_callout_prompt_text("/callout_prompt_text", false); | |||
| 1086 | if ( !icon->disabled && *cvar_callout_prompt_text ) | |||
| 1087 | { | |||
| 1088 | if ( CalloutMenu[player].calloutMenuIsOpen() && CalloutMenu[player].selectMoveTo ) | |||
| 1089 | { | |||
| 1090 | text->setDisabled(false); | |||
| 1091 | text->setText(Language::get(6049)); | |||
| 1092 | SDL_Rect pos = text->getSize(); | |||
| 1093 | pos.x = icon->pos.x + icon->pos.w + 4; | |||
| 1094 | pos.y = glyphAlignY - 10; | |||
| 1095 | text->setSize(pos); | |||
| 1096 | } | |||
| 1097 | } | |||
| 1098 | } | |||
| 1099 | ||||
| 1100 | void createAllyFollowerTitleFrame(const int player) | |||
| 1101 | { | |||
| 1102 | auto& hud_t = players[player]->hud; | |||
| 1103 | ||||
| 1104 | auto frame = hud_t.hudFrame->addFrame("follower title status"); | |||
| 1105 | hud_t.allyFollowerTitleFrame = frame; | |||
| 1106 | frame->setHollow(true); | |||
| 1107 | frame->setSize(SDL_Rect{ 0, 0, 300, 0 }); | |||
| 1108 | frame->setDisabled(true); | |||
| 1109 | ||||
| 1110 | auto selector = frame->addImage(SDL_Rect{ 0, 0, 8, 8 }, 0xFFFFFFFF, "*#images/ui/HUD/allies/HUD_Ally_Arrow_00.png", "selector"); | |||
| 1111 | selector->disabled = true; | |||
| 1112 | selector->ontop = true; | |||
| 1113 | ||||
| 1114 | auto glyphSelector = frame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "glyph selector"); | |||
| 1115 | glyphSelector->disabled = true; | |||
| 1116 | glyphSelector->ontop = true; | |||
| 1117 | } | |||
| 1118 | ||||
| 1119 | void createAllyPlayerFrame(const int player) | |||
| 1120 | { | |||
| 1121 | auto& hud_t = players[player]->hud; | |||
| 1122 | ||||
| 1123 | auto frame = hud_t.hudFrame->addFrame("player status"); | |||
| 1124 | hud_t.allyPlayerFrame = frame; | |||
| 1125 | frame->setHollow(true); | |||
| 1126 | frame->setSize(SDL_Rect{ 0, 0, 300, 0 }); | |||
| 1127 | frame->setDisabled(true); | |||
| 1128 | frame->setScrollBarsEnabled(false); | |||
| 1129 | frame->setAllowScrollBinds(false); | |||
| 1130 | } | |||
| 1131 | ||||
| 1132 | Frame* createAllyPlayerEntry(const int player) | |||
| 1133 | { | |||
| 1134 | auto& hud_t = players[player]->hud; | |||
| 1135 | Frame* baseFrame = hud_t.allyPlayerFrame; | |||
| 1136 | ||||
| 1137 | auto entry = baseFrame->addFrame("entry"); | |||
| 1138 | const int allyPlayerEntryHeight = 40; | |||
| 1139 | entry->setSize(SDL_Rect{ 0, 0, kPlayerBarsEntryFrameWidth, allyPlayerEntryHeight }); | |||
| 1140 | entry->setHollow(true); | |||
| 1141 | entry->setInheritParentFrameOpacity(false); | |||
| 1142 | ||||
| 1143 | Frame* portrait = nullptr; | |||
| 1144 | { | |||
| 1145 | portrait = entry->addFrame("portrait"); | |||
| 1146 | portrait->setSize(SDL_Rect{ 0, 0, 36, 36 }); | |||
| 1147 | portrait->addImage(SDL_Rect{ 0, 0, 32, 32 }, 0xFFFFFFFF, "*#images/ui/HUD/allies/HUD_HPBar_HeadDefaultM_00.png", "portrait img"); | |||
| 1148 | } | |||
| 1149 | ||||
| 1150 | std::string font = "fonts/pixel_maz.ttf#32#2"; | |||
| 1151 | { | |||
| 1152 | Field* name = entry->addField("name", 128); | |||
| 1153 | name->setFont(font.c_str()); | |||
| 1154 | name->setHJustify(Field::justify_t::LEFT); | |||
| 1155 | name->setVJustify(Field::justify_t::TOP); | |||
| 1156 | name->setSize(SDL_Rect{ portrait->getSize().x + portrait->getSize().w - 4, 0, entry->getSize().w, 24 }); | |||
| 1157 | name->setText(""); | |||
| 1158 | name->setColor(hudColors.characterSheetLightNeutral); | |||
| 1159 | name->setOntop(true); | |||
| 1160 | } | |||
| 1161 | { | |||
| 1162 | Field* level = entry->addField("level", 32); | |||
| 1163 | level->setFont("fonts/pixel_maz.ttf#32#2"); | |||
| 1164 | level->setHJustify(Field::justify_t::RIGHT); | |||
| 1165 | level->setVJustify(Field::justify_t::TOP); | |||
| 1166 | level->setSize(SDL_Rect{ 0, 14, entry->getSize().w - 16, 24 }); | |||
| 1167 | level->setText(""); | |||
| 1168 | level->setColor(hudColors.characterSheetLightNeutral); | |||
| 1169 | level->setOntop(true); | |||
| 1170 | } | |||
| 1171 | { | |||
| 1172 | Field* hp = entry->addField("hp", 32); | |||
| 1173 | hp->setFont(font.c_str()); | |||
| 1174 | hp->setHJustify(Field::justify_t::RIGHT); | |||
| 1175 | hp->setVJustify(Field::justify_t::TOP); | |||
| 1176 | hp->setSize(SDL_Rect{ 0, 0, entry->getSize().w - 16, 24 }); | |||
| 1177 | hp->setText(""); | |||
| 1178 | hp->setColor(makeColor(255, 255, 255, 255)); | |||
| 1179 | hp->setOntop(true); | |||
| 1180 | } | |||
| 1181 | ||||
| 1182 | const int hpHeight = 16; | |||
| 1183 | { | |||
| 1184 | Frame* hpFrame = entry->addFrame("hp"); | |||
| 1185 | hpFrame->setSize(SDL_Rect{ portrait->getSize().x + portrait->getSize().w - 4, 16, entry->getSize().w - (portrait->getSize().x + portrait->getSize().w - 4), hpHeight }); | |||
| 1186 | SDL_Rect hpFramePos = hpFrame->getSize(); | |||
| 1187 | hpFrame->setHollow(true); | |||
| 1188 | ||||
| 1189 | auto mid = hpFrame->addImage(SDL_Rect{ 6, 2, 40, 12 }, 0xFFFFFFFF, | |||
| 1190 | "*#images/ui/HUD/allies/HUD_HPBar_Mid_00.png", "hp img mid"); | |||
| 1191 | auto endCap = hpFrame->addImage(SDL_Rect{ mid->pos.x + mid->pos.w, 0, 6, 16 }, 0xFFFFFFFF, | |||
| 1192 | "*#images/ui/HUD/allies/HUD_HPBar_End_00.png", "hp img endcap"); | |||
| 1193 | ||||
| 1194 | auto progressBase = hpFrame->addImage(SDL_Rect{ 6, 4, 4, 8 }, 0xFFFFFFFF, | |||
| 1195 | "*#images/ui/HUD/allies/HUD_HPBar_Fill_Base_00.png", "hp img progress base"); | |||
| 1196 | auto progressMid = hpFrame->addImage(SDL_Rect{ 6, 4, 2, 8 }, 0xFFFFFFFF, | |||
| 1197 | "*#images/ui/HUD/allies/HUD_HPBar_Fill_Mid_00.png", "hp img progress"); | |||
| 1198 | auto progressEndCap = hpFrame->addImage(SDL_Rect{ 0, 4, 4, 8 }, 0xFFFFFFFF, | |||
| 1199 | "*#images/ui/HUD/allies/HUD_HPBar_Fill_End_00.png", "hp img progress endcap"); | |||
| 1200 | ||||
| 1201 | auto progressEndcapDamaged = hpFrame->addImage(SDL_Rect{ 6, 4, 18, 8 }, 0xFFFFFFFF, | |||
| 1202 | "*#images/ui/HUD/allies/HUD_HPBar_Fill_End_Damaged.png", "hp img progress damaged"); | |||
| 1203 | progressEndcapDamaged->disabled = true; | |||
| 1204 | ||||
| 1205 | auto progressEndCapFlash = hpFrame->addImage(SDL_Rect{ | |||
| 1206 | 0, 4, 18, 8 }, 0xFFFFFFFF, | |||
| 1207 | "*#images/ui/HUD/allies/HUD_HPBar_Fill_End_00.png", "hp img progress endcap flash"); | |||
| 1208 | progressEndCapFlash->disabled = true; | |||
| 1209 | ||||
| 1210 | auto base = hpFrame->addImage(SDL_Rect{ 0, 0, 6, 16 }, 0xFFFFFFFF, | |||
| 1211 | "*#images/ui/HUD/allies/HUD_HPBar_Base_00.png", "hp img base"); | |||
| 1212 | ||||
| 1213 | } | |||
| 1214 | ||||
| 1215 | const int mpHeight = 6; | |||
| 1216 | { | |||
| 1217 | Frame* mpFrame = entry->addFrame("mp"); | |||
| 1218 | mpFrame->setSize(SDL_Rect{ portrait->getSize().x + portrait->getSize().w, 30, entry->getSize().w - (portrait->getSize().x + portrait->getSize().w - 4), mpHeight }); | |||
| 1219 | SDL_Rect mpFramePos = mpFrame->getSize(); | |||
| 1220 | mpFrame->setHollow(true); | |||
| 1221 | ||||
| 1222 | auto mid = mpFrame->addImage(SDL_Rect{ 2, 0, 40, 6 }, 0xFFFFFFFF, | |||
| 1223 | "*#images/ui/HUD/allies/HUD_MPBar_Mid_00.png", "mp img mid"); | |||
| 1224 | auto endCap = mpFrame->addImage(SDL_Rect{ mid->pos.x + mid->pos.w, 0, 4, 6 }, 0xFFFFFFFF, | |||
| 1225 | "*#images/ui/HUD/allies/HUD_MPBar_End_00.png", "mp img endcap"); | |||
| 1226 | ||||
| 1227 | auto progressBase = mpFrame->addImage(SDL_Rect{ 2, 0, 4, 4 }, 0xFFFFFFFF, | |||
| 1228 | "*#images/ui/HUD/allies/HUD_MPBar_Fill_Base_00.png", "mp img progress base"); | |||
| 1229 | auto progressMid = mpFrame->addImage(SDL_Rect{ 2, 0, 4, 4 }, 0xFFFFFFFF, | |||
| 1230 | "*#images/ui/HUD/allies/HUD_MPBar_Fill_Mid_00.png", "mp img progress"); | |||
| 1231 | auto progressEndCap = mpFrame->addImage(SDL_Rect{ 0, 0, 4, 4 }, 0xFFFFFFFF, | |||
| 1232 | "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_00.png", "mp img progress endcap"); | |||
| 1233 | ||||
| 1234 | auto progressEndcapDamaged = mpFrame->addImage(SDL_Rect{ 0, 0, 8, 4 }, 0xFFFFFFFF, | |||
| 1235 | "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_Damaged.png", "mp img progress damaged"); | |||
| 1236 | progressEndcapDamaged->disabled = true; | |||
| 1237 | ||||
| 1238 | auto progressEndCapFlash = mpFrame->addImage(SDL_Rect{ | |||
| 1239 | 0, 0, 8, 4 }, 0xFFFFFFFF, | |||
| 1240 | "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_00.png", "mp img progress endcap flash"); | |||
| 1241 | progressEndCapFlash->disabled = true; | |||
| 1242 | ||||
| 1243 | auto base = mpFrame->addImage(SDL_Rect{ 0, 0, 4, 6 }, 0xFFFFFFFF, | |||
| 1244 | "*#images/ui/HUD/allies/HUD_MPBar_Base_00.png", "mp img base"); | |||
| 1245 | } | |||
| 1246 | ||||
| 1247 | entry->setDrawCallback([](const Widget& widget, SDL_Rect rect) { | |||
| 1248 | if ( widget.getUserData() && PingNetworkStatus_t::bEnabled ) | |||
| 1249 | { | |||
| 1250 | int player = reinterpret_cast<intptr_t>(widget.getUserData()) - 1; | |||
| 1251 | if ( player < 0 || player >= MAXPLAYERS4 ) { | |||
| 1252 | return; | |||
| 1253 | } | |||
| 1254 | ||||
| 1255 | auto value = PingNetworkStatus[player].displayMillisImmediate; | |||
| 1256 | const int divideInterval = 25; | |||
| 1257 | Image* img = nullptr; | |||
| 1258 | Image* warningImg = nullptr; | |||
| 1259 | if ( value > 0 ) | |||
| 1260 | { | |||
| 1261 | char buf[32]; | |||
| 1262 | if ( value < PingNetworkStatus_t::pingLimitGreen ) | |||
| 1263 | { | |||
| 1264 | if ( PingNetworkStatus[player].hudDisplayOKTicks == 0 ) | |||
| 1265 | { | |||
| 1266 | PingNetworkStatus[player].hudDisplayOKTicks = ticks; | |||
| 1267 | } | |||
| 1268 | if ( PingNetworkStatus_t::pingHUDDisplayGreen || | |||
| 1269 | (PingNetworkStatus_t::pingHUDShowOKBriefly | |||
| 1270 | && ((ticks - PingNetworkStatus[player].hudDisplayOKTicks) < 5 * TICKS_PER_SECOND50)) ) | |||
| 1271 | { | |||
| 1272 | img = Image::get("#*images/ui/HUD/Ping_Green.png"); | |||
| 1273 | } | |||
| 1274 | } | |||
| 1275 | else if ( value < PingNetworkStatus_t::pingLimitYellow ) | |||
| 1276 | { | |||
| 1277 | if ( PingNetworkStatus[player].hudDisplayOKTicks == 0 ) | |||
| 1278 | { | |||
| 1279 | PingNetworkStatus[player].hudDisplayOKTicks = ticks; | |||
| 1280 | } | |||
| 1281 | if ( PingNetworkStatus_t::pingHUDDisplayYellow || | |||
| 1282 | (PingNetworkStatus_t::pingHUDShowOKBriefly | |||
| 1283 | && ((ticks - PingNetworkStatus[player].hudDisplayOKTicks) < 5 * TICKS_PER_SECOND50)) ) | |||
| 1284 | { | |||
| 1285 | img = Image::get("#*images/ui/HUD/Ping_Yellow.png"); | |||
| 1286 | } | |||
| 1287 | } | |||
| 1288 | else if ( value < PingNetworkStatus_t::pingLimitOrange ) | |||
| 1289 | { | |||
| 1290 | PingNetworkStatus[player].hudDisplayOKTicks = 0; | |||
| 1291 | if ( PingNetworkStatus_t::pingHUDDisplayOrange ) | |||
| 1292 | { | |||
| 1293 | img = Image::get("#*images/ui/HUD/Ping_Orange.png"); | |||
| 1294 | warningImg = Image::get("#*images/ui/HUD/warning_glyph.png"); | |||
| 1295 | } | |||
| 1296 | } | |||
| 1297 | else | |||
| 1298 | { | |||
| 1299 | PingNetworkStatus[player].hudDisplayOKTicks = 0; | |||
| 1300 | if ( PingNetworkStatus_t::pingHUDDisplayRed ) | |||
| 1301 | { | |||
| 1302 | img = Image::get("#*images/ui/HUD/Ping_Red.png"); | |||
| 1303 | warningImg = Image::get("#*images/ui/HUD/danger_glyph.png"); | |||
| 1304 | } | |||
| 1305 | } | |||
| 1306 | } | |||
| 1307 | else | |||
| 1308 | { | |||
| 1309 | img = nullptr; | |||
| 1310 | PingNetworkStatus[player].hudDisplayOKTicks = 0; | |||
| 1311 | } | |||
| 1312 | if ( img ) | |||
| 1313 | { | |||
| 1314 | const auto frame = static_cast<const Frame*>(&widget); | |||
| 1315 | SDL_Rect pos = frame->getSize(); | |||
| 1316 | pos.x = pos.x + pos.w - 4; | |||
| 1317 | pos.y = pos.y + 8; | |||
| 1318 | pos.w = img->getWidth(); | |||
| 1319 | pos.h = img->getHeight(); | |||
| 1320 | img->drawColor(nullptr, pos, SDL_Rect{ 0, 0, Frame::virtualScreenX, Frame::virtualScreenY }, | |||
| 1321 | makeColor(255, 255, 255, 255 * (frame->getOpacity() / 100.0))); | |||
| 1322 | ||||
| 1323 | if ( warningImg ) | |||
| 1324 | { | |||
| 1325 | pos.y += 14; | |||
| 1326 | warningImg->drawColor(nullptr, pos, SDL_Rect{ 0, 0, Frame::virtualScreenX, Frame::virtualScreenY }, | |||
| 1327 | makeColor(255, 255, 255, 255 * (frame->getOpacity() / 100.0))); | |||
| 1328 | } | |||
| 1329 | ||||
| 1330 | if ( PingNetworkStatus_t::pingHUDShowNumericValue ) | |||
| 1331 | { | |||
| 1332 | pos.x += 20; | |||
| 1333 | pos.y = frame->getSize().y + 9; | |||
| 1334 | char buf[32]; | |||
| 1335 | snprintf(buf, sizeof(buf), "%dMS", PingNetworkStatus[player].displayMillis); | |||
| 1336 | if ( auto textGet = Text::get(buf, smallfont_outline, | |||
| 1337 | makeColor(134, 159, 165, 255), makeColor(0, 0, 0, 255)) ) | |||
| 1338 | { | |||
| 1339 | textGet->drawColor(SDL_Rect{ 0,0,0,0 }, SDL_Rect{ pos.x, pos.y, 0, 0 }, | |||
| 1340 | SDL_Rect{ 0, 0, Frame::virtualScreenX, Frame::virtualScreenY }, | |||
| 1341 | makeColor(255, 255, 255, 255 * (frame->getOpacity() / 100.0))); | |||
| 1342 | } | |||
| 1343 | } | |||
| 1344 | } | |||
| 1345 | } | |||
| 1346 | }); | |||
| 1347 | return entry; | |||
| 1348 | } | |||
| 1349 | ||||
| 1350 | Frame* createAllyFollowerEntry(const int player, Frame* baseFrame) | |||
| 1351 | { | |||
| 1352 | auto& hud_t = players[player]->hud; | |||
| 1353 | ||||
| 1354 | auto entry = baseFrame->addFrame("entry"); | |||
| 1355 | const int allyFollowerEntryHeight = 40; | |||
| 1356 | entry->setSize(SDL_Rect{ 0, 0, 300, allyFollowerEntryHeight }); | |||
| 1357 | entry->setHollow(true); | |||
| 1358 | entry->setInheritParentFrameOpacity(false); | |||
| 1359 | ||||
| 1360 | if ( baseFrame == players[player]->hud.allyFollowerTitleFrame ) | |||
| 1361 | { | |||
| 1362 | auto bgImg = entry->addImage(SDL_Rect{ 0, 0, 0, 0 }, makeColor(255, 255, 255, 255), "*images/ui/HUD/allies/HUD_Ally_TitleBG_Left_00.png", "bg img left"); | |||
| 1363 | bgImg->disabled = true; | |||
| 1364 | if ( auto imgGet = Image::get(bgImg->path.c_str()) ) | |||
| 1365 | { | |||
| 1366 | bgImg->pos.w = imgGet->getWidth(); | |||
| 1367 | bgImg->pos.h = imgGet->getHeight(); | |||
| 1368 | } | |||
| 1369 | ||||
| 1370 | bgImg = entry->addImage(SDL_Rect{ 0, 0, 0, 0 }, makeColor(255, 255, 255, 255), "*images/ui/HUD/allies/HUD_Ally_TitleBG_Mid_00.png", "bg img mid"); | |||
| 1371 | bgImg->disabled = true; | |||
| 1372 | if ( auto imgGet = Image::get(bgImg->path.c_str()) ) | |||
| 1373 | { | |||
| 1374 | bgImg->pos.w = imgGet->getWidth(); | |||
| 1375 | bgImg->pos.h = imgGet->getHeight(); | |||
| 1376 | } | |||
| 1377 | ||||
| 1378 | bgImg = entry->addImage(SDL_Rect{ 0, 0, 0, 0 }, makeColor(255, 255, 255, 255), "*images/ui/HUD/allies/HUD_Ally_TitleBG_Right_00.png", "bg img right"); | |||
| 1379 | bgImg->disabled = true; | |||
| 1380 | if ( auto imgGet = Image::get(bgImg->path.c_str()) ) | |||
| 1381 | { | |||
| 1382 | bgImg->pos.w = imgGet->getWidth(); | |||
| 1383 | bgImg->pos.h = imgGet->getHeight(); | |||
| 1384 | } | |||
| 1385 | } | |||
| 1386 | ||||
| 1387 | Frame* portrait = nullptr; | |||
| 1388 | { | |||
| 1389 | portrait = entry->addFrame("portrait"); | |||
| 1390 | portrait->setSize(SDL_Rect{ 0, 0, 36, 36 }); | |||
| 1391 | portrait->addImage(SDL_Rect{ 0, 0, 32, 32 }, 0xFFFFFFFF, "*#images/ui/HUD/allies/HUD_HPBar_HeadDefaultM_00.png", "portrait img"); | |||
| 1392 | } | |||
| 1393 | ||||
| 1394 | std::string font = "fonts/pixel_maz.ttf#32#2"; | |||
| 1395 | { | |||
| 1396 | Field* name = entry->addField("name", 128); | |||
| 1397 | name->setFont(font.c_str()); | |||
| 1398 | name->setHJustify(Field::justify_t::LEFT); | |||
| 1399 | name->setVJustify(Field::justify_t::TOP); | |||
| 1400 | name->setSize(SDL_Rect{ portrait->getSize().x + portrait->getSize().w - 4, 0, entry->getSize().w, 24 }); | |||
| 1401 | name->setText(""); | |||
| 1402 | name->setColor(hudColors.characterSheetLightNeutral); | |||
| 1403 | name->setOntop(true); | |||
| 1404 | } | |||
| 1405 | { | |||
| 1406 | Field* level = entry->addField("level", 32); | |||
| 1407 | level->setFont("fonts/pixel_maz.ttf#32#2"); | |||
| 1408 | level->setHJustify(Field::justify_t::RIGHT); | |||
| 1409 | level->setVJustify(Field::justify_t::TOP); | |||
| 1410 | level->setSize(SDL_Rect{ 0, 14, entry->getSize().w - 16, 24 }); | |||
| 1411 | level->setText(""); | |||
| 1412 | level->setColor(hudColors.characterSheetLightNeutral); | |||
| 1413 | level->setOntop(true); | |||
| 1414 | } | |||
| 1415 | { | |||
| 1416 | Field* hp = entry->addField("hp", 32); | |||
| 1417 | hp->setFont(font.c_str()); | |||
| 1418 | hp->setHJustify(Field::justify_t::RIGHT); | |||
| 1419 | hp->setVJustify(Field::justify_t::TOP); | |||
| 1420 | hp->setSize(SDL_Rect{ 0, 0, entry->getSize().w - 16, 24 }); | |||
| 1421 | hp->setText(""); | |||
| 1422 | hp->setColor(makeColor(255, 255, 255, 255)); | |||
| 1423 | hp->setOntop(true); | |||
| 1424 | } | |||
| 1425 | ||||
| 1426 | const int hpHeight = 16; | |||
| 1427 | { | |||
| 1428 | Frame* hpFrame = entry->addFrame("hp"); | |||
| 1429 | hpFrame->setSize(SDL_Rect{ portrait->getSize().x + portrait->getSize().w - 4, 16, entry->getSize().w - (portrait->getSize().x + portrait->getSize().w - 4), hpHeight }); | |||
| 1430 | SDL_Rect hpFramePos = hpFrame->getSize(); | |||
| 1431 | hpFrame->setHollow(true); | |||
| 1432 | ||||
| 1433 | auto mid = hpFrame->addImage(SDL_Rect{ 6, 2, 40, 12 }, 0xFFFFFFFF, | |||
| 1434 | "*#images/ui/HUD/allies/HUD_HPBar_Mid_00.png", "hp img mid"); | |||
| 1435 | auto endCap = hpFrame->addImage(SDL_Rect{ mid->pos.x + mid->pos.w, 0, 6, 16 }, 0xFFFFFFFF, | |||
| 1436 | "*#images/ui/HUD/allies/HUD_HPBar_End_00.png", "hp img endcap"); | |||
| 1437 | ||||
| 1438 | auto progressBase = hpFrame->addImage(SDL_Rect{ 6, 4, 4, 8 }, 0xFFFFFFFF, | |||
| 1439 | "*#images/ui/HUD/allies/HUD_HPBar_Fill_Base_00.png", "hp img progress base"); | |||
| 1440 | auto progressMid = hpFrame->addImage(SDL_Rect{ 6, 4, 2, 8 }, 0xFFFFFFFF, | |||
| 1441 | "*#images/ui/HUD/allies/HUD_HPBar_Fill_Mid_00.png", "hp img progress"); | |||
| 1442 | auto progressEndCap = hpFrame->addImage(SDL_Rect{ 0, 4, 4, 8 }, 0xFFFFFFFF, | |||
| 1443 | "*#images/ui/HUD/allies/HUD_HPBar_Fill_End_00.png", "hp img progress endcap"); | |||
| 1444 | ||||
| 1445 | auto progressEndcapDamaged = hpFrame->addImage(SDL_Rect{ 6, 4, 18, 8 }, 0xFFFFFFFF, | |||
| 1446 | "*#images/ui/HUD/allies/HUD_HPBar_Fill_End_Damaged.png", "hp img progress damaged"); | |||
| 1447 | progressEndcapDamaged->disabled = true; | |||
| 1448 | ||||
| 1449 | auto progressEndCapFlash = hpFrame->addImage(SDL_Rect{ | |||
| 1450 | 0, 4, 18, 8 }, 0xFFFFFFFF, | |||
| 1451 | "*#images/ui/HUD/allies/HUD_HPBar_Fill_End_00.png", "hp img progress endcap flash"); | |||
| 1452 | progressEndCapFlash->disabled = true; | |||
| 1453 | ||||
| 1454 | auto base = hpFrame->addImage(SDL_Rect{ 0, 0, 6, 16 }, 0xFFFFFFFF, | |||
| 1455 | "*#images/ui/HUD/allies/HUD_HPBar_Base_00.png", "hp img base"); | |||
| 1456 | ||||
| 1457 | } | |||
| 1458 | ||||
| 1459 | const int mpHeight = 6; | |||
| 1460 | if ( false ) | |||
| 1461 | { | |||
| 1462 | Frame* mpFrame = entry->addFrame("mp"); | |||
| 1463 | mpFrame->setSize(SDL_Rect{ portrait->getSize().x + portrait->getSize().w, 30, entry->getSize().w - (portrait->getSize().x + portrait->getSize().w - 4), mpHeight }); | |||
| 1464 | SDL_Rect mpFramePos = mpFrame->getSize(); | |||
| 1465 | mpFrame->setHollow(true); | |||
| 1466 | ||||
| 1467 | auto mid = mpFrame->addImage(SDL_Rect{ 2, 0, 40, 6 }, 0xFFFFFFFF, | |||
| 1468 | "*#images/ui/HUD/allies/HUD_MPBar_Mid_00.png", "mp img mid"); | |||
| 1469 | auto endCap = mpFrame->addImage(SDL_Rect{ mid->pos.x + mid->pos.w, 0, 4, 6 }, 0xFFFFFFFF, | |||
| 1470 | "*#images/ui/HUD/allies/HUD_MPBar_End_00.png", "mp img endcap"); | |||
| 1471 | ||||
| 1472 | auto progressBase = mpFrame->addImage(SDL_Rect{ 2, 0, 4, 4 }, 0xFFFFFFFF, | |||
| 1473 | "*#images/ui/HUD/allies/HUD_MPBar_Fill_Base_00.png", "mp img progress base"); | |||
| 1474 | auto progressMid = mpFrame->addImage(SDL_Rect{ 2, 0, 4, 4 }, 0xFFFFFFFF, | |||
| 1475 | "*#images/ui/HUD/allies/HUD_MPBar_Fill_Mid_00.png", "mp img progress"); | |||
| 1476 | auto progressEndCap = mpFrame->addImage(SDL_Rect{ 0, 0, 4, 4 }, 0xFFFFFFFF, | |||
| 1477 | "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_00.png", "mp img progress endcap"); | |||
| 1478 | ||||
| 1479 | auto progressEndcapDamaged = mpFrame->addImage(SDL_Rect{ 0, 0, 8, 4 }, 0xFFFFFFFF, | |||
| 1480 | "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_Damaged.png", "mp img progress damaged"); | |||
| 1481 | progressEndcapDamaged->disabled = true; | |||
| 1482 | ||||
| 1483 | auto progressEndCapFlash = mpFrame->addImage(SDL_Rect{ | |||
| 1484 | 0, 0, 8, 4 }, 0xFFFFFFFF, | |||
| 1485 | "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_00.png", "mp img progress endcap flash"); | |||
| 1486 | progressEndCapFlash->disabled = true; | |||
| 1487 | ||||
| 1488 | auto base = mpFrame->addImage(SDL_Rect{ 0, 0, 4, 6 }, 0xFFFFFFFF, | |||
| 1489 | "*#images/ui/HUD/allies/HUD_MPBar_Base_00.png", "mp img base"); | |||
| 1490 | } | |||
| 1491 | return entry; | |||
| 1492 | } | |||
| 1493 | ||||
| 1494 | bool Player::HUD_t::FollowerDisplay_t::infiniteScrolling = true; | |||
| 1495 | int Player::HUD_t::FollowerDisplay_t::numFiniteBars = 8;; | |||
| 1496 | int Player::HUD_t::FollowerDisplay_t::numInfiniteFullsizeBars = 8; | |||
| 1497 | int Player::HUD_t::FollowerDisplay_t::numInfiniteCompactBars = 16; | |||
| 1498 | int Player::HUD_t::FollowerDisplay_t::numInfiniteSplitscreenFullsizeBars = 4; | |||
| 1499 | int Player::HUD_t::FollowerDisplay_t::numInfiniteSplitscreenCompactBars = 8; | |||
| 1500 | int Player::HUD_t::FollowerDisplay_t::getNumEntriesToShow(const int playernum) | |||
| 1501 | { | |||
| 1502 | auto& hud_t = players[playernum]->hud; | |||
| 1503 | if ( !infiniteScrolling ) | |||
| 1504 | { | |||
| 1505 | return numFiniteBars; | |||
| 1506 | } | |||
| 1507 | if ( !splitscreen || !players[playernum]->bUseCompactGUIHeight() ) | |||
| 1508 | { | |||
| 1509 | if ( list_Size(&stats[playernum]->FOLLOWERS) < numInfiniteFullsizeBars ) | |||
| 1510 | { | |||
| 1511 | return numInfiniteFullsizeBars; | |||
| 1512 | } | |||
| 1513 | else | |||
| 1514 | { | |||
| 1515 | return numInfiniteCompactBars; | |||
| 1516 | } | |||
| 1517 | } | |||
| 1518 | else | |||
| 1519 | { | |||
| 1520 | if ( list_Size(&stats[playernum]->FOLLOWERS) < numInfiniteSplitscreenFullsizeBars ) | |||
| 1521 | { | |||
| 1522 | return numInfiniteSplitscreenFullsizeBars; | |||
| 1523 | } | |||
| 1524 | else | |||
| 1525 | { | |||
| 1526 | return numInfiniteSplitscreenCompactBars; | |||
| 1527 | } | |||
| 1528 | } | |||
| 1529 | } | |||
| 1530 | ||||
| 1531 | bool Player::HUD_t::FollowerDisplay_t::getCompactMode(const int playernum) | |||
| 1532 | { | |||
| 1533 | auto& hud_t = players[playernum]->hud; | |||
| 1534 | if ( !infiniteScrolling ) | |||
| 1535 | { | |||
| 1536 | return false; | |||
| 1537 | } | |||
| 1538 | if ( !splitscreen || !players[playernum]->bUseCompactGUIHeight() ) | |||
| 1539 | { | |||
| 1540 | if ( list_Size(&stats[playernum]->FOLLOWERS) < numInfiniteFullsizeBars ) | |||
| 1541 | { | |||
| 1542 | return false; | |||
| 1543 | } | |||
| 1544 | else | |||
| 1545 | { | |||
| 1546 | return true; | |||
| 1547 | } | |||
| 1548 | } | |||
| 1549 | else | |||
| 1550 | { | |||
| 1551 | if ( list_Size(&stats[playernum]->FOLLOWERS) < numInfiniteSplitscreenFullsizeBars ) | |||
| 1552 | { | |||
| 1553 | return false; | |||
| 1554 | } | |||
| 1555 | else | |||
| 1556 | { | |||
| 1557 | return true; | |||
| 1558 | } | |||
| 1559 | } | |||
| 1560 | } | |||
| 1561 | ||||
| 1562 | Frame* getAllyBarTitleFrameEntry(const int player) | |||
| 1563 | { | |||
| 1564 | auto& hud_t = players[player]->hud; | |||
| 1565 | Frame* entry = hud_t.allyFollowerTitleFrame->findFrame("entry"); | |||
| 1566 | if ( !entry ) | |||
| 1567 | { | |||
| 1568 | entry = createAllyFollowerEntry(player, hud_t.allyFollowerTitleFrame); | |||
| 1569 | } | |||
| 1570 | return entry; | |||
| 1571 | } | |||
| 1572 | ||||
| 1573 | void updateAllyBarFrame(const int player, Frame* baseFrame, int activeBars, int realActiveBars, const bool bPlayerBars) | |||
| 1574 | { | |||
| 1575 | Frame::image_t* selector = baseFrame->findImage("selector"); | |||
| 1576 | if ( selector ) | |||
| 1577 | { | |||
| 1578 | selector->disabled = true; | |||
| 1579 | } | |||
| 1580 | Frame::image_t* titleSelector = !bPlayerBars ? players[player]->hud.allyFollowerTitleFrame->findImage("selector") : nullptr; | |||
| 1581 | if ( titleSelector ) | |||
| 1582 | { | |||
| 1583 | titleSelector->disabled = true; | |||
| 1584 | } | |||
| 1585 | Frame::image_t* titleSelectorGlyph = !bPlayerBars ? players[player]->hud.allyFollowerTitleFrame->findImage("glyph selector") : nullptr; | |||
| 1586 | if ( titleSelectorGlyph ) | |||
| 1587 | { | |||
| 1588 | titleSelectorGlyph->disabled = true; | |||
| 1589 | } | |||
| 1590 | ||||
| 1591 | std::vector<Frame*> allyFrames; | |||
| 1592 | int barIndex = -1; | |||
| 1593 | for ( auto f : baseFrame->getFrames() ) | |||
| 1594 | { | |||
| 1595 | if ( strcmp(f->getName(), "entry") || f->isToBeDeleted() ) | |||
| 1596 | { | |||
| 1597 | continue; | |||
| 1598 | } | |||
| 1599 | ++barIndex; | |||
| 1600 | ||||
| 1601 | if ( barIndex >= activeBars ) | |||
| 1602 | { | |||
| 1603 | f->removeSelf(); | |||
| 1604 | continue; | |||
| 1605 | } | |||
| 1606 | allyFrames.push_back(f); | |||
| 1607 | } | |||
| 1608 | ||||
| 1609 | while ( allyFrames.size() < activeBars ) | |||
| 1610 | { | |||
| 1611 | allyFrames.push_back(bPlayerBars ? createAllyPlayerEntry(player) : createAllyFollowerEntry(player, baseFrame)); | |||
| 1612 | } | |||
| 1613 | ||||
| 1614 | auto& hud_t = players[player]->hud; | |||
| 1615 | ||||
| 1616 | Uint32 recentFollowerUID = 0; | |||
| 1617 | if ( FollowerMenu[player].recentEntity ) | |||
| 1618 | { | |||
| 1619 | recentFollowerUID = FollowerMenu[player].recentEntity->getUID(); | |||
| 1620 | } | |||
| 1621 | ||||
| 1622 | auto& infiniteScrolling = Player::HUD_t::FollowerDisplay_t::infiniteScrolling; | |||
| 1623 | /*if ( enableDebugKeys && keystatus[SDLK_F] ) | |||
| 1624 | { | |||
| 1625 | keystatus[SDLK_F] = 0; | |||
| 1626 | infiniteScrolling = !infiniteScrolling; | |||
| 1627 | }*/ | |||
| 1628 | ||||
| 1629 | auto& followerDisplay = hud_t.followerDisplay; | |||
| 1630 | ||||
| 1631 | Frame* titleFrame = nullptr; | |||
| 1632 | if ( infiniteScrolling && !bPlayerBars ) | |||
| 1633 | { | |||
| 1634 | titleFrame = getAllyBarTitleFrameEntry(player); | |||
| 1635 | titleFrame->setDisabled(true); | |||
| 1636 | } | |||
| 1637 | ||||
| 1638 | const int kNumEntriesToShow = Player::HUD_t::FollowerDisplay_t::getNumEntriesToShow(player); | |||
| 1639 | ||||
| 1640 | int currentY = 0; | |||
| 1641 | int entryHeightForGlyphs = 0; | |||
| 1642 | int baseFrameHeight = 0; | |||
| 1643 | int selectorX = 0; | |||
| 1644 | bool madeSelection = false; | |||
| 1645 | bool updateTitleFrame = false; | |||
| 1646 | bool doneTitleFrame = false; | |||
| 1647 | barIndex = -1; | |||
| 1648 | bool halfWidthBars = (splitscreen && players[player]->bUseCompactGUIWidth()) | |||
| 1649 | /*|| (enableDebugKeys && keystatus[SDLK_G])*/; | |||
| 1650 | ||||
| 1651 | std::set<Uint32> followerUids; | |||
| 1652 | for ( node_t* node = stats[player]->FOLLOWERS.first; node != nullptr; node = node->next ) | |||
| 1653 | { | |||
| 1654 | if ( (Uint32*)node->element ) | |||
| 1655 | { | |||
| 1656 | followerUids.emplace(*((Uint32*)node->element)); | |||
| 1657 | } | |||
| 1658 | } | |||
| 1659 | ||||
| 1660 | for ( auto it = (bPlayerBars ? hud_t.playerBars.begin() : hud_t.followerBars.begin()); | |||
| 1661 | it != (bPlayerBars ? hud_t.playerBars.end() : hud_t.followerBars.end()); ) | |||
| 1662 | { | |||
| 1663 | ++barIndex; | |||
| 1664 | auto& followerBar = (*it).second; | |||
| 1665 | Frame* entryFrame = allyFrames[barIndex]; | |||
| 1666 | ||||
| 1667 | bool doAnimation = true; | |||
| 1668 | bool shortBars = players[player]->hud.followerDisplay.bCompact && infiniteScrolling && !bPlayerBars; | |||
| 1669 | if ( followerBar.dummy ) | |||
| 1670 | { | |||
| 1671 | doAnimation = true; | |||
| 1672 | } | |||
| 1673 | else if ( followerBar.selected ) | |||
| 1674 | { | |||
| 1675 | if ( updateTitleFrame ) | |||
| 1676 | { | |||
| 1677 | shortBars = false; | |||
| 1678 | entryFrame = titleFrame; | |||
| 1679 | titleFrame->setDisabled(false); | |||
| 1680 | doneTitleFrame = true; | |||
| 1681 | doAnimation = false; | |||
| 1682 | } | |||
| 1683 | } | |||
| 1684 | ||||
| 1685 | auto& HPBar = followerBar.hpBar; | |||
| 1686 | auto& MPBar = followerBar.mpBar; | |||
| 1687 | ||||
| 1688 | if ( doAnimation ) | |||
| 1689 | { | |||
| 1690 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 1691 | /*if ( !players[player]->shootmode && !FollowerMenu[player].followerMenuIsOpen() ) | |||
| 1692 | { | |||
| 1693 | real_t setpointDiffX = fpsScale * std::max(.01, (followerBar.animx)) / 2.0; | |||
| 1694 | followerBar.animx -= setpointDiffX; | |||
| 1695 | followerBar.animx = std::max(0.0, followerBar.animx); | |||
| 1696 | } | |||
| 1697 | else*/ | |||
| 1698 | { | |||
| 1699 | real_t setpointDiffX = fpsScale * std::max(.01, (1.0 - followerBar.animx)) / 2.0; | |||
| 1700 | followerBar.animx += setpointDiffX; | |||
| 1701 | followerBar.animx = std::min(1.0, followerBar.animx); | |||
| 1702 | } | |||
| 1703 | } | |||
| 1704 | ||||
| 1705 | SDL_Rect pos = entryFrame->getSize(); | |||
| 1706 | pos.x = pos.w - followerBar.animx * pos.w; | |||
| 1707 | if ( halfWidthBars && !bPlayerBars ) | |||
| 1708 | { | |||
| 1709 | pos.x += 8; | |||
| 1710 | } | |||
| 1711 | if ( updateTitleFrame ) | |||
| 1712 | { | |||
| 1713 | pos.y = hud_t.allyFollowerTitleFrame->getSize().h - AllyStatusBarSettings_t::FollowerBars_t::entrySettings.entryHeight * 2; | |||
| 1714 | } | |||
| 1715 | else | |||
| 1716 | { | |||
| 1717 | pos.y = currentY; | |||
| 1718 | } | |||
| 1719 | if ( bPlayerBars ) | |||
| 1720 | { | |||
| 1721 | if ( shortBars ) | |||
| 1722 | { | |||
| 1723 | pos.h = AllyStatusBarSettings_t::PlayerBars_t::entrySettings.entryCompactHeight; | |||
| 1724 | } | |||
| 1725 | else | |||
| 1726 | { | |||
| 1727 | pos.h = AllyStatusBarSettings_t::PlayerBars_t::entrySettings.entryHeight; | |||
| 1728 | } | |||
| 1729 | } | |||
| 1730 | else | |||
| 1731 | { | |||
| 1732 | if ( shortBars ) | |||
| 1733 | { | |||
| 1734 | pos.h = AllyStatusBarSettings_t::FollowerBars_t::entrySettings.entryCompactHeight; | |||
| 1735 | } | |||
| 1736 | else | |||
| 1737 | { | |||
| 1738 | pos.h = AllyStatusBarSettings_t::FollowerBars_t::entrySettings.entryHeight; | |||
| 1739 | } | |||
| 1740 | entryHeightForGlyphs = pos.h; | |||
| 1741 | } | |||
| 1742 | if ( bPlayerBars ) | |||
| 1743 | { | |||
| 1744 | baseFrameHeight += pos.h; | |||
| 1745 | } | |||
| 1746 | else | |||
| 1747 | { | |||
| 1748 | if ( !infiniteScrolling ) | |||
| 1749 | { | |||
| 1750 | if ( barIndex < kNumEntriesToShow ) | |||
| 1751 | { | |||
| 1752 | baseFrameHeight += pos.h; | |||
| 1753 | } | |||
| 1754 | } | |||
| 1755 | else | |||
| 1756 | { | |||
| 1757 | if ( !shortBars && !updateTitleFrame ) | |||
| 1758 | { | |||
| 1759 | baseFrameHeight = (((kNumEntriesToShow - 1)) | |||
| 1760 | * AllyStatusBarSettings_t::FollowerBars_t::entrySettings.entryHeight); | |||
| 1761 | } | |||
| 1762 | else | |||
| 1763 | { | |||
| 1764 | baseFrameHeight = (((kNumEntriesToShow - 1)) | |||
| 1765 | * AllyStatusBarSettings_t::FollowerBars_t::entrySettings.entryCompactHeight); | |||
| 1766 | } | |||
| 1767 | } | |||
| 1768 | } | |||
| 1769 | entryFrame->setOpacity(baseFrame->getOpacity()); | |||
| 1770 | ||||
| 1771 | ||||
| 1772 | if ( followerBar.expired && ((ticks - followerBar.expiredTicks) > TICKS_PER_SECOND50 / 2) ) | |||
| 1773 | { | |||
| 1774 | if ( doAnimation ) | |||
| 1775 | { | |||
| 1776 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 1777 | real_t setpointDiffFade = fpsScale * std::max(.01, (1.0 - followerBar.animFade)) / 5.0; | |||
| 1778 | followerBar.animFade += setpointDiffFade; | |||
| 1779 | followerBar.animFade = std::min(1.0, followerBar.animFade); | |||
| 1780 | } | |||
| 1781 | entryFrame->setOpacity(entryFrame->getOpacity() * (1.0 - followerBar.animFade)); | |||
| 1782 | ||||
| 1783 | if ( doAnimation && followerBar.animFade >= 0.9999 ) | |||
| 1784 | { | |||
| 1785 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 1786 | real_t setpointDiffY = fpsScale * std::max(.01, (1.0 - followerBar.animy)) / 2.0; | |||
| 1787 | followerBar.animy += setpointDiffY; | |||
| 1788 | followerBar.animy = std::min(1.0, followerBar.animy); | |||
| 1789 | } | |||
| 1790 | pos.h *= (1.0 - followerBar.animy); | |||
| 1791 | } | |||
| 1792 | ||||
| 1793 | Uint32 uid = (*it).first; | |||
| 1794 | Entity* follower = bPlayerBars ? players[uid]->entity : uidToEntity(uid); | |||
| 1795 | if ( (!bPlayerBars && (!follower || followerUids.find(uid) == followerUids.end())) || (bPlayerBars && client_disconnected[uid]) ) | |||
| 1796 | { | |||
| 1797 | if ( !followerBar.expired ) | |||
| 1798 | { | |||
| 1799 | followerBar.expiredTicks = ticks; | |||
| 1800 | followerBar.animFadeScroll = 0.0; | |||
| 1801 | followerBar.animFadeScrollDummy = 1.0; | |||
| 1802 | } | |||
| 1803 | followerBar.expired = true; | |||
| 1804 | followerBar.selected = false; | |||
| 1805 | } | |||
| 1806 | ||||
| 1807 | if ( bPlayerBars ) | |||
| 1808 | { | |||
| 1809 | entryFrame->setUserData(followerBar.expired ? nullptr : (void*)(intptr_t)(uid + 1)); // 0 is nullptr, so +1 | |||
| 1810 | } | |||
| 1811 | ||||
| 1812 | if ( !bPlayerBars ) | |||
| 1813 | { | |||
| 1814 | if ( doAnimation ) | |||
| 1815 | { | |||
| 1816 | if ( hud_t.followerBars.size() > kNumEntriesToShow && !infiniteScrolling ) | |||
| 1817 | { | |||
| 1818 | if ( barIndex >= followerDisplay.scrollSetpoint | |||
| 1819 | && barIndex < (followerDisplay.scrollSetpoint + kNumEntriesToShow) ) | |||
| 1820 | { | |||
| 1821 | // visible in list | |||
| 1822 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 1823 | real_t setpointDiffFade = fpsScale * std::max(.01, followerBar.animFadeScroll) / 1.0; | |||
| 1824 | followerBar.animFadeScroll -= setpointDiffFade; | |||
| 1825 | followerBar.animFadeScroll = std::max(0.0, followerBar.animFadeScroll); | |||
| 1826 | } | |||
| 1827 | else | |||
| 1828 | { | |||
| 1829 | // not visible | |||
| 1830 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 1831 | real_t setpointDiffFade = fpsScale * std::max(.01, (1.0 - followerBar.animFadeScroll)) / 1.0; | |||
| 1832 | followerBar.animFadeScroll += setpointDiffFade; | |||
| 1833 | followerBar.animFadeScroll = std::min(1.0, followerBar.animFadeScroll); | |||
| 1834 | } | |||
| 1835 | } | |||
| 1836 | else | |||
| 1837 | { | |||
| 1838 | if ( infiniteScrolling | |||
| 1839 | && (barIndex < followerDisplay.scrollSetpoint | |||
| 1840 | // below statement fades real bars if the list is truncated because of JSON config. | |||
| 1841 | // if list not truncated, then no real bar should show up until scroll resets to 0 | |||
| 1842 | || barIndex >= followerDisplay.scrollSetpoint + kNumEntriesToShow - 1) ) | |||
| 1843 | { | |||
| 1844 | //followerBar.animFadeScroll = 1.0; | |||
| 1845 | // not visible | |||
| 1846 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 1847 | if ( !followerBar.dummy ) | |||
| 1848 | { | |||
| 1849 | real_t setpointDiffFade = fpsScale * std::max(.01, (1.0 - followerBar.animFadeScroll)) / 10.0; | |||
| 1850 | followerBar.animFadeScroll += setpointDiffFade; | |||
| 1851 | followerBar.animFadeScroll = std::min(1.0, followerBar.animFadeScroll); | |||
| 1852 | } | |||
| 1853 | ||||
| 1854 | } | |||
| 1855 | else | |||
| 1856 | { | |||
| 1857 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 1858 | if ( !followerBar.dummy ) | |||
| 1859 | { | |||
| 1860 | real_t setpointDiffFade = fpsScale * std::max(.01, followerBar.animFadeScroll) / 10.0; | |||
| 1861 | followerBar.animFadeScroll -= setpointDiffFade; | |||
| 1862 | followerBar.animFadeScroll = std::max(0.0, followerBar.animFadeScroll); | |||
| 1863 | } | |||
| 1864 | ||||
| 1865 | } | |||
| 1866 | ||||
| 1867 | if ( infiniteScrolling | |||
| 1868 | && (barIndex < followerDisplay.scrollSetpoint - 1 | |||
| 1869 | // below statement stops dummy bars fading in if the list is truncated because of JSON config. | |||
| 1870 | // otherwise fade in as the real bar is less than the current scroll | |||
| 1871 | && !(barIndex + realActiveBars >= followerDisplay.scrollSetpoint + kNumEntriesToShow - 1)) ) | |||
| 1872 | { | |||
| 1873 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 1874 | if ( !followerBar.dummy ) | |||
| 1875 | { | |||
| 1876 | real_t setpointDiffFade = fpsScale * std::max(.01, followerBar.animFadeScrollDummy) / 10.0; | |||
| 1877 | followerBar.animFadeScrollDummy -= setpointDiffFade; | |||
| 1878 | followerBar.animFadeScrollDummy = std::max(0.0, followerBar.animFadeScrollDummy); | |||
| 1879 | } | |||
| 1880 | } | |||
| 1881 | else | |||
| 1882 | { | |||
| 1883 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 1884 | if ( !followerBar.dummy ) | |||
| 1885 | { | |||
| 1886 | real_t setpointDiffFade = fpsScale * std::max(.01, (1.0 - followerBar.animFadeScrollDummy)) / 10.0; | |||
| 1887 | followerBar.animFadeScrollDummy += setpointDiffFade; | |||
| 1888 | followerBar.animFadeScrollDummy = std::min(1.0, followerBar.animFadeScrollDummy); | |||
| 1889 | } | |||
| 1890 | } | |||
| 1891 | } | |||
| 1892 | } | |||
| 1893 | ||||
| 1894 | if ( !updateTitleFrame ) | |||
| 1895 | { | |||
| 1896 | bool fadeWhenMenuOpen = FollowerMenu[player].followerMenuIsOpen() && halfWidthBars; | |||
| 1897 | real_t dim = .5; | |||
| 1898 | if ( followerBar.dummy ) | |||
| 1899 | { | |||
| 1900 | entryFrame->setOpacity(entryFrame->getOpacity() * (1.0 - followerBar.animFadeScrollDummy) * (fadeWhenMenuOpen ? dim : 1.0)); | |||
| 1901 | } | |||
| 1902 | else | |||
| 1903 | { | |||
| 1904 | entryFrame->setOpacity(entryFrame->getOpacity() * (1.0 - followerBar.animFadeScroll) * (fadeWhenMenuOpen ? dim : 1.0)); | |||
| 1905 | } | |||
| 1906 | } | |||
| 1907 | } | |||
| 1908 | ||||
| 1909 | if ( !updateTitleFrame ) | |||
| 1910 | { | |||
| 1911 | currentY += pos.h; | |||
| 1912 | } | |||
| 1913 | entryFrame->setSize(pos); | |||
| 1914 | ||||
| 1915 | auto hpFrame = entryFrame->findFrame("hp"); | |||
| 1916 | auto hpMid = hpFrame->findImage("hp img mid"); | |||
| 1917 | auto hpEndcap = hpFrame->findImage("hp img endcap"); | |||
| 1918 | auto hpProgressBase = hpFrame->findImage("hp img progress base"); | |||
| 1919 | auto hpProgress = hpFrame->findImage("hp img progress"); | |||
| 1920 | auto hpProgressEndcap = hpFrame->findImage("hp img progress endcap"); | |||
| 1921 | ||||
| 1922 | auto& hpBarSettings = bPlayerBars ? AllyStatusBarSettings_t::PlayerBars_t::hpBar : AllyStatusBarSettings_t::FollowerBars_t::hpBar; | |||
| 1923 | auto& mpBarSettings = bPlayerBars ? AllyStatusBarSettings_t::PlayerBars_t::mpBar : AllyStatusBarSettings_t::FollowerBars_t::mpBar; | |||
| 1924 | const int hpCompactMaxWidthAmount = hpBarSettings.barCompactMaxWidthAmount; | |||
| 1925 | const int hpMaxWidthAmount = hpBarSettings.barMaxWidthAmount; | |||
| 1926 | const real_t hpCompactWidthIncreasePercentOnInterval = hpBarSettings.barCompactWidthIncreasePercentOnInterval; | |||
| 1927 | const real_t hpWidthIncreasePercentOnInterval = hpBarSettings.barWidthIncreasePercentOnInterval; | |||
| 1928 | const int hpCompactIntervalToIncreaseWidth = hpBarSettings.barCompactIntervalToIncreaseWidth; | |||
| 1929 | const int hpIntervalToIncreaseWidth = hpBarSettings.barIntervalToIncreaseWidth; | |||
| 1930 | const int hpCompactBasePercentSize = hpBarSettings.barCompactBasePercentSize; | |||
| 1931 | const int hpBasePercentSize = hpBarSettings.barBasePercentSize; | |||
| 1932 | ||||
| 1933 | const real_t hpCompactIntervalStartValue = hpBarSettings.barCompactIntervalStartValue; | |||
| 1934 | const real_t hpIntervalStartValue = hpBarSettings.barIntervalStartValue; | |||
| 1935 | ||||
| 1936 | const int mpCompactMaxWidthAmount = mpBarSettings.barCompactMaxWidthAmount; | |||
| 1937 | const int mpMaxWidthAmount = mpBarSettings.barMaxWidthAmount; | |||
| 1938 | const real_t mpCompactWidthIncreasePercentOnInterval = mpBarSettings.barCompactWidthIncreasePercentOnInterval; | |||
| 1939 | const real_t mpWidthIncreasePercentOnInterval = mpBarSettings.barWidthIncreasePercentOnInterval; | |||
| 1940 | const int mpCompactIntervalToIncreaseWidth = mpBarSettings.barCompactIntervalToIncreaseWidth; | |||
| 1941 | const int mpIntervalToIncreaseWidth = mpBarSettings.barIntervalToIncreaseWidth; | |||
| 1942 | const int mpCompactBasePercentSize = mpBarSettings.barCompactBasePercentSize; | |||
| 1943 | const int mpBasePercentSize = mpBarSettings.barBasePercentSize; | |||
| 1944 | ||||
| 1945 | const real_t mpCompactIntervalStartValue = mpBarSettings.barCompactIntervalStartValue; | |||
| 1946 | const real_t mpIntervalStartValue = mpBarSettings.barIntervalStartValue; | |||
| 1947 | ||||
| 1948 | Stat* followerStats = nullptr; | |||
| 1949 | if ( bPlayerBars ) | |||
| 1950 | { | |||
| 1951 | followerStats = stats[uid]; | |||
| 1952 | } | |||
| 1953 | else | |||
| 1954 | { | |||
| 1955 | followerStats = follower ? follower->getStats() : nullptr; | |||
| 1956 | } | |||
| 1957 | ||||
| 1958 | int MAXHP = HPBar.maxValue; | |||
| 1959 | int HP = HPBar.animateSetpoint; | |||
| 1960 | int MAXMP = MPBar.maxValue; | |||
| 1961 | int MP = MPBar.animateSetpoint; | |||
| 1962 | Field* nameField = entryFrame->findField("name"); | |||
| 1963 | bool updateName = false; | |||
| 1964 | if ( followerBar.name == "" || followerDisplay.bHalfWidthBars != halfWidthBars || updateTitleFrame ) | |||
| 1965 | { | |||
| 1966 | updateName = true; | |||
| 1967 | } | |||
| 1968 | ||||
| 1969 | if ( followerStats && ((!bPlayerBars && follower) || bPlayerBars) ) | |||
| 1970 | { | |||
| 1971 | followerBar.level = followerStats->LVL; | |||
| 1972 | if ( follower ) | |||
| 1973 | { | |||
| 1974 | followerBar.monsterType = follower->getMonsterTypeFromSprite(); | |||
| 1975 | followerBar.model = follower->sprite; | |||
| 1976 | } | |||
| 1977 | else | |||
| 1978 | { | |||
| 1979 | followerBar.monsterType = followerStats->type; | |||
| 1980 | } | |||
| 1981 | ||||
| 1982 | if ( HP != followerStats->HP || MAXHP != followerStats->MAXHP ) | |||
| 1983 | { | |||
| 1984 | updateName = true; | |||
| 1985 | } | |||
| 1986 | HP = followerStats->HP; | |||
| 1987 | MAXHP = followerStats->MAXHP; | |||
| 1988 | ||||
| 1989 | MP = followerStats->MP; | |||
| 1990 | MAXMP = followerStats->MAXMP; | |||
| 1991 | } | |||
| 1992 | else | |||
| 1993 | { | |||
| 1994 | if ( !bPlayerBars ) | |||
| 1995 | { | |||
| 1996 | HP = 0; | |||
| 1997 | } | |||
| 1998 | } | |||
| 1999 | ||||
| 2000 | if ( updateName && (followerStats && ((!bPlayerBars && follower) || bPlayerBars)) ) | |||
| 2001 | { | |||
| 2002 | std::string followerName = ""; | |||
| 2003 | followerBar.customPortraitPath = ""; | |||
| 2004 | size_t maxNameLen = 0; | |||
| 2005 | if ( bPlayerBars ) | |||
| 2006 | { | |||
| 2007 | maxNameLen = AllyStatusBarSettings_t::PlayerBars_t::entrySettings.maxNameLengthFullsize; | |||
| 2008 | } | |||
| 2009 | else | |||
| 2010 | { | |||
| 2011 | if ( !halfWidthBars ) | |||
| 2012 | { | |||
| 2013 | if ( !shortBars ) | |||
| 2014 | { | |||
| 2015 | maxNameLen = AllyStatusBarSettings_t::FollowerBars_t::entrySettings.maxNameLengthFullsize; | |||
| 2016 | } | |||
| 2017 | else | |||
| 2018 | { | |||
| 2019 | maxNameLen = AllyStatusBarSettings_t::FollowerBars_t::entrySettings.maxNameLengthCompact; | |||
| 2020 | } | |||
| 2021 | } | |||
| 2022 | else | |||
| 2023 | { | |||
| 2024 | if ( !shortBars ) | |||
| 2025 | { | |||
| 2026 | maxNameLen = AllyStatusBarSettings_t::FollowerBars_t::entrySettings.maxNameLengthSplitscreenFullsize; | |||
| 2027 | } | |||
| 2028 | else | |||
| 2029 | { | |||
| 2030 | maxNameLen = AllyStatusBarSettings_t::FollowerBars_t::entrySettings.maxNameLengthSplitscreenCompact; | |||
| 2031 | } | |||
| 2032 | } | |||
| 2033 | if ( !shortBars ) | |||
| 2034 | { | |||
| 2035 | if ( MAXHP >= 100 || HP >= 100 ) | |||
| 2036 | { | |||
| 2037 | maxNameLen -= 1; | |||
| 2038 | } | |||
| 2039 | if ( MAXHP >= 100 && HP >= 100 ) | |||
| 2040 | { | |||
| 2041 | maxNameLen -= 1; | |||
| 2042 | } | |||
| 2043 | if ( MAXHP >= 200 && HP >= 200 ) | |||
| 2044 | { | |||
| 2045 | maxNameLen -= 1; | |||
| 2046 | } | |||
| 2047 | } | |||
| 2048 | } | |||
| 2049 | ||||
| 2050 | if ( bPlayerBars ) | |||
| 2051 | { | |||
| 2052 | followerName = followerStats->name; | |||
| 2053 | if ( followerName.size() > maxNameLen ) | |||
| 2054 | { | |||
| 2055 | followerName = followerName.substr(0, maxNameLen - 1); | |||
| 2056 | followerName += ".."; | |||
| 2057 | } | |||
| 2058 | } | |||
| 2059 | else if ( strcmp(followerStats->name, "") && strcmp(followerStats->name, "nothing") ) | |||
| 2060 | { | |||
| 2061 | if ( strlen(followerStats->name) > maxNameLen ) | |||
| 2062 | { | |||
| 2063 | if ( followerStats->type == SKELETON ) | |||
| 2064 | { | |||
| 2065 | if ( MonsterData_t::nameMatchesSpecialNPCName(*followerStats, "skeleton sentinel") ) | |||
| 2066 | { | |||
| 2067 | followerName = MonsterData_t::monsterDataEntries[SKELETON].specialNPCs["skeleton sentinel"].shortname; | |||
| 2068 | followerBar.customPortraitPath = MonsterData_t::monsterDataEntries[SKELETON].specialNPCs["skeleton sentinel"].uniqueIcon; | |||
| 2069 | } | |||
| 2070 | else if ( MonsterData_t::nameMatchesSpecialNPCName(*followerStats, "skeleton knight") ) | |||
| 2071 | { | |||
| 2072 | followerName = MonsterData_t::monsterDataEntries[SKELETON].specialNPCs["skeleton knight"].shortname; | |||
| 2073 | followerBar.customPortraitPath = MonsterData_t::monsterDataEntries[SKELETON].specialNPCs["skeleton knight"].uniqueIcon; | |||
| 2074 | } | |||
| 2075 | else | |||
| 2076 | { | |||
| 2077 | followerName = followerStats->name; | |||
| 2078 | } | |||
| 2079 | } | |||
| 2080 | else | |||
| 2081 | { | |||
| 2082 | followerName = followerStats->name; | |||
| 2083 | } | |||
| 2084 | ||||
| 2085 | if ( followerName.size() > maxNameLen ) | |||
| 2086 | { | |||
| 2087 | followerName = followerName.substr(0, maxNameLen - 1); | |||
| 2088 | followerName += ".."; | |||
| 2089 | } | |||
| 2090 | } | |||
| 2091 | else | |||
| 2092 | { | |||
| 2093 | followerName = followerStats->name; | |||
| 2094 | } | |||
| 2095 | } | |||
| 2096 | else | |||
| 2097 | { | |||
| 2098 | followerName = getMonsterLocalizedName(followerStats->type); | |||
| 2099 | if ( followerName.size() > maxNameLen ) | |||
| 2100 | { | |||
| 2101 | if ( MonsterData_t::monsterDataEntries[followerStats->type].defaultShortDisplayName != "" ) | |||
| 2102 | { | |||
| 2103 | followerName = MonsterData_t::monsterDataEntries[followerStats->type].defaultShortDisplayName; | |||
| 2104 | } | |||
| 2105 | if ( followerName.size() > maxNameLen ) | |||
| 2106 | { | |||
| 2107 | followerName = followerName.substr(0, maxNameLen - 1); | |||
| 2108 | followerName += ".."; | |||
| 2109 | } | |||
| 2110 | } | |||
| 2111 | } | |||
| 2112 | capitalizeString(followerName); | |||
| 2113 | followerBar.name = followerName; | |||
| 2114 | } | |||
| 2115 | ||||
| 2116 | char levelbuf[32]; | |||
| 2117 | snprintf(levelbuf, sizeof(levelbuf), "Lv%d", followerBar.level); | |||
| 2118 | auto levelField = entryFrame->findField("level"); | |||
| 2119 | levelField->setText(levelbuf); | |||
| 2120 | ||||
| 2121 | char buf[32]; | |||
| 2122 | snprintf(buf, sizeof(buf), "%d/%d", HP, MAXHP); | |||
| 2123 | auto hpField = entryFrame->findField("hp"); | |||
| 2124 | hpField->setText(buf); | |||
| 2125 | ||||
| 2126 | if ( bPlayerBars ) | |||
| 2127 | { | |||
| 2128 | static ConsoleVariable<bool> cvar_playerbars_use_colors("/playerbars_use_colors", true); | |||
| 2129 | if ( *cvar_playerbars_use_colors ) | |||
| 2130 | { | |||
| 2131 | nameField->setColor(playerColor(uid, colorblind_lobby, false)); | |||
| 2132 | } | |||
| 2133 | else | |||
| 2134 | { | |||
| 2135 | nameField->setColor(hudColors.characterSheetLightNeutral); | |||
| 2136 | } | |||
| 2137 | } | |||
| 2138 | else | |||
| 2139 | { | |||
| 2140 | nameField->setColor(hudColors.characterSheetLightNeutral); | |||
| 2141 | } | |||
| 2142 | nameField->setText(followerBar.name.c_str()); | |||
| 2143 | ||||
| 2144 | int hpWidth = (shortBars ? hpBarSettings.barCompactPixelWidth : hpBarSettings.barPixelWidth); | |||
| 2145 | if ( halfWidthBars ) | |||
| 2146 | { | |||
| 2147 | hpWidth += hpBarSettings.barSplitscreenPixelWidthOffset; | |||
| 2148 | } | |||
| 2149 | ||||
| 2150 | Frame* portrait = entryFrame->findFrame("portrait"); | |||
| 2151 | if ( shortBars ) | |||
| 2152 | { | |||
| 2153 | portrait->setDisabled(true); | |||
| 2154 | SDL_Rect hpFramePos = hpFrame->getSize(); | |||
| 2155 | hpFramePos.x = levelField->getSize().w - 40 - (hpWidth + 6); | |||
| 2156 | hpFramePos.y = 4; | |||
| 2157 | hpFrame->setSize(hpFramePos); | |||
| 2158 | ||||
| 2159 | hpField->setDisabled(true); | |||
| 2160 | ||||
| 2161 | nameField->setSize(SDL_Rect{ 0, 0, hpFramePos.x - 8, nameField->getSize().h }); | |||
| 2162 | nameField->setHJustify(Field::justify_t::RIGHT); | |||
| 2163 | ||||
| 2164 | levelField->setSize(SDL_Rect{ 0, nameField->getSize().y, entryFrame->getSize().w - 16, levelField->getSize().h }); | |||
| 2165 | ||||
| 2166 | if ( !followerDisplay.infiniteScrolling ) | |||
| 2167 | { | |||
| 2168 | if ( auto textGet = nameField->getTextObject() ) | |||
| 2169 | { | |||
| 2170 | int x = nameField->getSize().x + nameField->getSize().w - textGet->getWidth(); | |||
| 2171 | selectorX = selectorX != 0 ? std::min(selectorX, x) : x; | |||
| 2172 | } | |||
| 2173 | } | |||
| 2174 | } | |||
| 2175 | else | |||
| 2176 | { | |||
| 2177 | portrait->setDisabled(false); | |||
| 2178 | SDL_Rect hpFramePos = hpFrame->getSize(); | |||
| 2179 | hpFramePos.x = levelField->getSize().w - 40 - (hpWidth + 6); | |||
| 2180 | hpFramePos.y = 16; | |||
| 2181 | hpFrame->setSize(hpFramePos); | |||
| 2182 | ||||
| 2183 | hpField->setDisabled(false); | |||
| 2184 | ||||
| 2185 | portrait->setSize(SDL_Rect{ hpFramePos.x + 4 - portrait->getSize().w, 0, portrait->getSize().w, portrait->getSize().h }); | |||
| 2186 | auto portraitImg = portrait->findImage("portrait img"); | |||
| 2187 | if ( followerBar.customPortraitPath != "" ) | |||
| 2188 | { | |||
| 2189 | portraitImg->path = followerBar.customPortraitPath; | |||
| 2190 | } | |||
| 2191 | else | |||
| 2192 | { | |||
| 2193 | portraitImg->path = monsterData.getAllyIconFromSprite(followerBar.model, followerBar.monsterType); | |||
| 2194 | } | |||
| 2195 | ||||
| 2196 | nameField->setSize(SDL_Rect{ hpFramePos.x, 0, entryFrame->getSize().w - hpFramePos.x, nameField->getSize().h }); | |||
| 2197 | nameField->setHJustify(Field::justify_t::LEFT); | |||
| 2198 | ||||
| 2199 | levelField->setSize(SDL_Rect{ 0, 14, entryFrame->getSize().w - 16, levelField->getSize().h }); | |||
| 2200 | ||||
| 2201 | if ( !followerDisplay.infiniteScrolling ) | |||
| 2202 | { | |||
| 2203 | selectorX = selectorX != 0 ? std::min(selectorX, portrait->getSize().x) : portrait->getSize().x; | |||
| 2204 | } | |||
| 2205 | } | |||
| 2206 | ||||
| 2207 | if ( updateTitleFrame ) | |||
| 2208 | { | |||
| 2209 | auto bgImgLeft = entryFrame->findImage("bg img left"); | |||
| 2210 | bgImgLeft->disabled = false; | |||
| 2211 | auto bgImgMid = entryFrame->findImage("bg img mid"); | |||
| 2212 | bgImgMid->disabled = false; | |||
| 2213 | auto bgImgRight = entryFrame->findImage("bg img right"); | |||
| 2214 | bgImgRight->disabled = false; | |||
| 2215 | ||||
| 2216 | const int totalWidth = entryFrame->getSize().w - portrait->getSize().x; | |||
| 2217 | bgImgMid->pos.w = totalWidth - bgImgLeft->pos.w - bgImgRight->pos.w; | |||
| 2218 | /*bgImg->pos.h = entryFrame->getSize().h;*/ | |||
| 2219 | bgImgLeft->pos.y = 0; | |||
| 2220 | bgImgMid->pos.y = 0; | |||
| 2221 | bgImgRight->pos.y = 0; | |||
| 2222 | bgImgLeft->pos.x = entryFrame->getSize().w - totalWidth - 8; | |||
| 2223 | bgImgMid->pos.x = bgImgLeft->pos.x + bgImgLeft->pos.w; | |||
| 2224 | bgImgRight->pos.x = bgImgMid->pos.x + bgImgMid->pos.w; | |||
| 2225 | ||||
| 2226 | selectorX = bgImgLeft->pos.x; | |||
| 2227 | } | |||
| 2228 | ||||
| 2229 | { // HP | |||
| 2230 | int backgroundWidth = hpWidth - 6; | |||
| 2231 | real_t progressWidth = hpWidth - 8; | |||
| 2232 | ||||
| 2233 | // handle bar size changing | |||
| 2234 | { | |||
| 2235 | real_t multiplier = 1.0; | |||
| 2236 | const Sint32 maxHPWidth = (shortBars ? hpCompactMaxWidthAmount : hpMaxWidthAmount); | |||
| 2237 | if ( MAXHP < maxHPWidth ) | |||
| 2238 | { | |||
| 2239 | // start at 30%, increase 2.5% every 5 HP past 20 MAXHP | |||
| 2240 | multiplier = (shortBars ? hpCompactBasePercentSize : hpBasePercentSize) / 100.0; | |||
| 2241 | real_t widthIntervalPercent = (shortBars ? hpCompactWidthIncreasePercentOnInterval : hpWidthIncreasePercentOnInterval) / 100.0; | |||
| 2242 | int intervalThreshold = (shortBars ? hpCompactIntervalToIncreaseWidth : hpIntervalToIncreaseWidth); | |||
| 2243 | int baseIntervalStart = (shortBars ? hpCompactIntervalStartValue : hpIntervalStartValue); | |||
| 2244 | multiplier += (widthIntervalPercent * ((std::max(0, MAXHP - baseIntervalStart) / intervalThreshold))); | |||
| 2245 | } | |||
| 2246 | ||||
| 2247 | int diff = static_cast<int>(std::max(0.0, progressWidth - progressWidth * multiplier)); // how many pixels the progress bar shrinks | |||
| 2248 | progressWidth -= diff; // scale the progress bars | |||
| 2249 | hpMid->pos.w = backgroundWidth - diff; // move the background bar by x pixels as above | |||
| 2250 | hpEndcap->pos.x = hpMid->pos.x + hpMid->pos.w; // move the background endcap by x pixels as above | |||
| 2251 | } | |||
| 2252 | ||||
| 2253 | HPBar.animatePreviousSetpoint = HPBar.animateSetpoint; | |||
| 2254 | real_t& hpForegroundValue = HPBar.animateValue; | |||
| 2255 | real_t& hpFadedValue = HPBar.animateValue2; | |||
| 2256 | ||||
| 2257 | HPBar.animateSetpoint = HP; | |||
| 2258 | if ( HPBar.animateSetpoint < HPBar.animatePreviousSetpoint ) // insta-change as losing health | |||
| 2259 | { | |||
| 2260 | hpForegroundValue = HPBar.animateSetpoint; | |||
| 2261 | HPBar.animateTicks = ticks; | |||
| 2262 | ||||
| 2263 | // flash for taking damage | |||
| 2264 | HPBar.flashTicks = ticks; | |||
| 2265 | HPBar.flashAnimState = -1; | |||
| 2266 | HPBar.flashType = Player::HUD_t::FLASH_ON_DAMAGE; | |||
| 2267 | } | |||
| 2268 | ||||
| 2269 | if ( HPBar.maxValue > MAXHP ) | |||
| 2270 | { | |||
| 2271 | hpFadedValue = HPBar.animateSetpoint; // resetting game etc, stop fade animation sticking out of frame | |||
| 2272 | } | |||
| 2273 | ||||
| 2274 | HPBar.maxValue = MAXHP; | |||
| 2275 | if ( !followerBar.bInit ) | |||
| 2276 | { | |||
| 2277 | hpForegroundValue = HPBar.animateSetpoint; | |||
| 2278 | } | |||
| 2279 | if ( hpForegroundValue < HPBar.animateSetpoint ) // gaining HP, animate | |||
| 2280 | { | |||
| 2281 | // flash for gaining HP, provided not already flashing | |||
| 2282 | /*if ( HPBar.flashAnimState == -1 || (HPBar.flashAnimState >= 0 && HPBar.flashType != FLASH_ON_DAMAGE) ) | |||
| 2283 | { | |||
| 2284 | HPBar.flashTicks = ticks; | |||
| 2285 | HPBar.flashAnimState = -1; | |||
| 2286 | HPBar.flashType = FLASH_ON_RECOVERY; | |||
| 2287 | }*/ | |||
| 2288 | ||||
| 2289 | if ( doAnimation ) | |||
| 2290 | { | |||
| 2291 | real_t setpointDiff = std::max(0.0, HPBar.animateSetpoint - hpForegroundValue); | |||
| 2292 | real_t fpsScale = getFPSScale(144.0); | |||
| 2293 | hpForegroundValue += fpsScale * (setpointDiff / 20.0); // reach it in 20 intervals, scaled to FPS | |||
| 2294 | } | |||
| 2295 | hpForegroundValue = std::min(static_cast<real_t>(HPBar.animateSetpoint), hpForegroundValue); | |||
| 2296 | ||||
| 2297 | if ( abs(HPBar.animateSetpoint) - abs(hpForegroundValue) <= 1.0 ) | |||
| 2298 | { | |||
| 2299 | hpForegroundValue = HPBar.animateSetpoint; | |||
| 2300 | } | |||
| 2301 | ||||
| 2302 | /* int increment = 3; | |||
| 2303 | double scaledIncrement = (increment * (getFPSScale(144.0)));*/ | |||
| 2304 | //real_t diff = std::max(.1, (HPBar.animateSetpoint * 10 - hpForegroundValue) / (maxValue / 5)); // 0.1-5 value | |||
| 2305 | //if ( HPBar.animateSetpoint * 10 >= maxValue ) | |||
| 2306 | //{ | |||
| 2307 | // diff = 5; | |||
| 2308 | //} | |||
| 2309 | //scaledIncrement *= 0.2 * pow(diff, 2) + .5; | |||
| 2310 | ||||
| 2311 | //hpForegroundValue = std::min(HPBar.animateSetpoint * 10.0, hpForegroundValue + scaledIncrement); | |||
| 2312 | //messagePlayer(0, "%.2f | %.2f", hpForegroundValue); | |||
| 2313 | } | |||
| 2314 | else if ( hpForegroundValue > HPBar.animateSetpoint ) // losing HP, snap to value | |||
| 2315 | { | |||
| 2316 | hpForegroundValue = HPBar.animateSetpoint; | |||
| 2317 | } | |||
| 2318 | ||||
| 2319 | if ( hpFadedValue < HPBar.animateSetpoint ) | |||
| 2320 | { | |||
| 2321 | hpFadedValue = hpForegroundValue; | |||
| 2322 | HPBar.animateTicks = ticks; | |||
| 2323 | } | |||
| 2324 | else if ( hpFadedValue > HPBar.animateSetpoint ) | |||
| 2325 | { | |||
| 2326 | if ( ticks - HPBar.animateTicks > 30 /*|| stats[player.playernum]->HP <= 0*/ ) // fall after x ticks | |||
| 2327 | { | |||
| 2328 | if ( doAnimation ) | |||
| 2329 | { | |||
| 2330 | real_t setpointDiff = std::max(0.01, hpFadedValue - HPBar.animateSetpoint); | |||
| 2331 | real_t fpsScale = getFPSScale(144.0); | |||
| 2332 | hpFadedValue -= fpsScale * (setpointDiff / 20.0); // reach it in 20 intervals, scaled to FPS | |||
| 2333 | } | |||
| 2334 | hpFadedValue = std::max(static_cast<real_t>(HPBar.animateSetpoint), hpFadedValue); | |||
| 2335 | } | |||
| 2336 | } | |||
| 2337 | else | |||
| 2338 | { | |||
| 2339 | HPBar.animateTicks = ticks; | |||
| 2340 | } | |||
| 2341 | ||||
| 2342 | real_t foregroundPercent = hpForegroundValue / HPBar.maxValue; | |||
| 2343 | hpProgress->pos.w = std::max(1, static_cast<int>((progressWidth)* foregroundPercent)); | |||
| 2344 | hpProgressEndcap->pos.x = hpProgress->pos.x + hpProgress->pos.w; | |||
| 2345 | ||||
| 2346 | auto hpProgressEndcapDamaged = hpFrame->findImage("hp img progress damaged"); | |||
| 2347 | hpProgressEndcapDamaged->disabled = true; | |||
| 2348 | hpProgressEndcapDamaged->pos.x = hpProgressEndcap->pos.x + (hpProgressEndcap->pos.w - hpProgressEndcapDamaged->pos.w); | |||
| 2349 | if ( hpForegroundValue < HPBar.maxValue ) // damaged | |||
| 2350 | { | |||
| 2351 | hpProgressEndcapDamaged->disabled = false; | |||
| 2352 | } | |||
| 2353 | ||||
| 2354 | real_t fadePercent = hpFadedValue / HPBar.maxValue; | |||
| 2355 | if ( HP <= 0 ) | |||
| 2356 | { | |||
| 2357 | // hide all the progress elements when dead, as endcap/base don't shrink | |||
| 2358 | // hpProgress width 0px defaults to original size, so hide that too | |||
| 2359 | hpProgress->disabled = true; | |||
| 2360 | hpProgressEndcap->disabled = true; | |||
| 2361 | hpProgressBase->disabled = true; | |||
| 2362 | hpProgressEndcapDamaged->disabled = true; | |||
| 2363 | } | |||
| 2364 | else | |||
| 2365 | { | |||
| 2366 | hpProgress->disabled = false; | |||
| 2367 | hpProgressEndcap->disabled = false; | |||
| 2368 | hpProgressBase->disabled = false; | |||
| 2369 | } | |||
| 2370 | ||||
| 2371 | auto hpProgressEndCapFlash = hpFrame->findImage("hp img progress endcap flash"); | |||
| 2372 | hpProgressEndCapFlash->disabled = true; | |||
| 2373 | const int framesPerAnimation = HPBar.flashType == Player::HUD_t::FLASH_ON_DAMAGE ? 1 : 2; | |||
| 2374 | const int numAnimationFrames = HPBar.flashType == Player::HUD_t::FLASH_ON_DAMAGE ? 20 : 2; | |||
| 2375 | if ( HPBar.flashTicks > 0 ) | |||
| 2376 | { | |||
| 2377 | //messagePlayer(0, MESSAGE_DEBUG, "ticks: %d, animticks: %d, state: %d", ticks, HPBarFlashTicks, HPBarFlashAnimState); | |||
| 2378 | if ( HPBar.flashAnimState > numAnimationFrames || hpProgress->disabled ) | |||
| 2379 | { | |||
| 2380 | HPBar.flashTicks = 0; | |||
| 2381 | HPBar.flashType = Player::HUD_t::FLASH_ON_DAMAGE; | |||
| 2382 | HPBar.flashAnimState = -1; | |||
| 2383 | hpProgressEndCapFlash->disabled = true; | |||
| 2384 | } | |||
| 2385 | else | |||
| 2386 | { | |||
| 2387 | hpProgressEndCapFlash->disabled = hpProgressEndcap->disabled; | |||
| 2388 | if ( ticks == HPBar.flashTicks ) | |||
| 2389 | { | |||
| 2390 | HPBar.flashAnimState = 1; | |||
| 2391 | HPBar.flashProcessedOnTick = ticks; | |||
| 2392 | } | |||
| 2393 | else if ( (HPBar.flashProcessedOnTick != ticks) | |||
| 2394 | && (ticks > HPBar.flashTicks) | |||
| 2395 | && (ticks - HPBar.flashTicks) % framesPerAnimation == 0 ) | |||
| 2396 | { | |||
| 2397 | ++HPBar.flashAnimState; | |||
| 2398 | HPBar.flashProcessedOnTick = ticks; | |||
| 2399 | } | |||
| 2400 | ||||
| 2401 | if ( HPBar.flashType == Player::HUD_t::FLASH_ON_DAMAGE ) | |||
| 2402 | { | |||
| 2403 | if ( HPBar.flashAnimState <= 6 ) | |||
| 2404 | { | |||
| 2405 | hpProgressEndCapFlash->color = 0xFFFFFFFF; | |||
| 2406 | } | |||
| 2407 | ||||
| 2408 | if ( HPBar.flashAnimState == 0 ) | |||
| 2409 | { | |||
| 2410 | hpProgress->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Mid_00.png"; | |||
| 2411 | hpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_End_F00.png"; | |||
| 2412 | hpProgressBase->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Base_00.png"; | |||
| 2413 | } | |||
| 2414 | else if ( HPBar.flashAnimState >= 1 && HPBar.flashAnimState <= 2 ) | |||
| 2415 | { | |||
| 2416 | hpProgress->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Mid_01.png"; | |||
| 2417 | hpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_End_F01.png"; | |||
| 2418 | hpProgressBase->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Base_01.png"; | |||
| 2419 | } | |||
| 2420 | else if ( HPBar.flashAnimState == 3 ) | |||
| 2421 | { | |||
| 2422 | hpProgress->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Mid_02.png"; | |||
| 2423 | hpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_End_F02.png"; | |||
| 2424 | hpProgressBase->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Base_02.png"; | |||
| 2425 | } | |||
| 2426 | else if ( HPBar.flashAnimState >= 4 && HPBar.flashAnimState <= 5 ) | |||
| 2427 | { | |||
| 2428 | hpProgress->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Mid_01.png"; | |||
| 2429 | hpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_End_F01.png"; | |||
| 2430 | hpProgressBase->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Base_01.png"; | |||
| 2431 | } | |||
| 2432 | else if ( HPBar.flashAnimState == 6 ) | |||
| 2433 | { | |||
| 2434 | hpProgress->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Mid_03.png"; | |||
| 2435 | hpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_End_F03.png"; | |||
| 2436 | hpProgressBase->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Base_03.png"; | |||
| 2437 | } | |||
| 2438 | else | |||
| 2439 | { | |||
| 2440 | hpProgress->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Mid_00.png"; | |||
| 2441 | hpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_End_F00.png"; | |||
| 2442 | hpProgressBase->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Base_00.png"; | |||
| 2443 | Uint8 r, g, b, a; | |||
| 2444 | getColor(hpProgressEndCapFlash->color, &r, &g, &b, &a); | |||
| 2445 | int decrement = 20; | |||
| 2446 | real_t fpsScale = getFPSScale(60.0); | |||
| 2447 | decrement *= fpsScale; | |||
| 2448 | a = std::max(0, (int)a - decrement); | |||
| 2449 | hpProgressEndCapFlash->color = makeColor(r, g, b, a); | |||
| 2450 | } | |||
| 2451 | } | |||
| 2452 | else | |||
| 2453 | { | |||
| 2454 | hpProgressEndCapFlash->color = 0xFFFFFFFF; | |||
| 2455 | hpProgressEndCapFlash->disabled = true; | |||
| 2456 | if ( HPBar.flashAnimState == 1 ) | |||
| 2457 | { | |||
| 2458 | hpProgress->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Mid_03.png"; | |||
| 2459 | hpProgressBase->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Base_03.png"; | |||
| 2460 | hpProgressEndcap->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_End_03.png"; | |||
| 2461 | } | |||
| 2462 | } | |||
| 2463 | } | |||
| 2464 | } | |||
| 2465 | else | |||
| 2466 | { | |||
| 2467 | HPBar.flashAnimState = -1; | |||
| 2468 | hpProgressEndCapFlash->disabled = true; | |||
| 2469 | hpProgress->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Mid_00.png"; | |||
| 2470 | hpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_End_F00.png"; | |||
| 2471 | hpProgressBase->path = "*#images/ui/HUD/allies/HUD_HPBar_Fill_Base_00.png"; | |||
| 2472 | } | |||
| 2473 | if ( !hpProgressEndcap->disabled ) | |||
| 2474 | { | |||
| 2475 | hpProgressEndCapFlash->pos.x = hpProgressEndcap->pos.x - (hpProgressEndCapFlash->pos.w - hpProgressEndcap->pos.w); | |||
| 2476 | } | |||
| 2477 | } | |||
| 2478 | ||||
| 2479 | auto mpFrame = entryFrame->findFrame("mp"); | |||
| 2480 | if ( mpFrame ) | |||
| 2481 | { // MP | |||
| 2482 | auto mpMid = mpFrame->findImage("mp img mid"); | |||
| 2483 | auto mpEndcap = mpFrame->findImage("mp img endcap"); | |||
| 2484 | auto mpProgressBase = mpFrame->findImage("mp img progress base"); | |||
| 2485 | auto mpProgress = mpFrame->findImage("mp img progress"); | |||
| 2486 | auto mpProgressEndcap = mpFrame->findImage("mp img progress endcap"); | |||
| 2487 | ||||
| 2488 | const int mpWidth = (shortBars ? mpBarSettings.barCompactPixelWidth : mpBarSettings.barPixelWidth); | |||
| 2489 | int backgroundWidth = mpWidth - 2; | |||
| 2490 | real_t progressWidth = mpWidth - 4; | |||
| 2491 | // handle bar size changing | |||
| 2492 | { | |||
| 2493 | real_t multiplier = 1.0; | |||
| 2494 | const Sint32 maxMPWidth = (shortBars ? mpCompactMaxWidthAmount : mpMaxWidthAmount); | |||
| 2495 | if ( MAXMP < maxMPWidth ) | |||
| 2496 | { | |||
| 2497 | // start at 30%, increase 2.5% every 5 MP past 20 MAXMP | |||
| 2498 | multiplier = (shortBars ? mpCompactBasePercentSize : mpBasePercentSize) / 100.0; | |||
| 2499 | real_t widthIntervalPercent = (shortBars ? mpCompactWidthIncreasePercentOnInterval : mpWidthIncreasePercentOnInterval) / 100.0; | |||
| 2500 | int intervalThreshold = (shortBars ? mpCompactIntervalToIncreaseWidth : mpIntervalToIncreaseWidth); | |||
| 2501 | int baseIntervalStart = (shortBars ? mpCompactIntervalStartValue : mpIntervalStartValue); | |||
| 2502 | multiplier += (widthIntervalPercent * ((std::max(0, MAXMP - baseIntervalStart) / intervalThreshold))); | |||
| 2503 | } | |||
| 2504 | ||||
| 2505 | int diff = static_cast<int>(std::max(0.0, progressWidth - progressWidth * multiplier)); // how many pixels the progress bar shrinks | |||
| 2506 | progressWidth -= diff; // scale the progress bars | |||
| 2507 | mpMid->pos.w = backgroundWidth - diff; // move the background bar by x pixels as above | |||
| 2508 | mpEndcap->pos.x = mpMid->pos.x + mpMid->pos.w; // move the background endcap by x pixels as above | |||
| 2509 | } | |||
| 2510 | ||||
| 2511 | MPBar.animatePreviousSetpoint = MPBar.animateSetpoint; | |||
| 2512 | real_t& mpForegroundValue = MPBar.animateValue; | |||
| 2513 | real_t& mpFadedValue = MPBar.animateValue2; | |||
| 2514 | ||||
| 2515 | MPBar.animateSetpoint = MP; | |||
| 2516 | if ( MPBar.animateSetpoint < MPBar.animatePreviousSetpoint ) // insta-change as losing health | |||
| 2517 | { | |||
| 2518 | mpForegroundValue = MPBar.animateSetpoint; | |||
| 2519 | MPBar.animateTicks = ticks; | |||
| 2520 | ||||
| 2521 | // flash for taking damage | |||
| 2522 | MPBar.flashTicks = ticks; | |||
| 2523 | MPBar.flashProcessedOnTick = 0; | |||
| 2524 | MPBar.flashAnimState = -1; | |||
| 2525 | MPBar.flashType = Player::HUD_t::FLASH_ON_DAMAGE; | |||
| 2526 | } | |||
| 2527 | ||||
| 2528 | if ( MPBar.maxValue > MAXMP ) | |||
| 2529 | { | |||
| 2530 | mpFadedValue = MPBar.animateSetpoint; // resetting game etc, stop fade animation sticking out of frame | |||
| 2531 | } | |||
| 2532 | ||||
| 2533 | MPBar.maxValue = MAXMP; | |||
| 2534 | if ( !followerBar.bInit ) | |||
| 2535 | { | |||
| 2536 | mpForegroundValue = MPBar.animateSetpoint; | |||
| 2537 | } | |||
| 2538 | if ( mpForegroundValue < MPBar.animateSetpoint ) // gaining MP, animate | |||
| 2539 | { | |||
| 2540 | // flash for gaining MP, provided not already flashing | |||
| 2541 | /*if ( MPBar.flashAnimState == -1 || (MPBar.flashAnimState >= 0 && MPBar.flashType != FLASH_ON_DAMAGE) ) | |||
| 2542 | { | |||
| 2543 | MPBar.flashTicks = ticks; | |||
| 2544 | MPBar.flashAnimState = -1; | |||
| 2545 | MPBar.flashType = FLASH_ON_RECOVERY; | |||
| 2546 | }*/ | |||
| 2547 | if ( doAnimation ) | |||
| 2548 | { | |||
| 2549 | real_t setpointDiff = std::max(.1, MPBar.animateSetpoint - mpForegroundValue); | |||
| 2550 | real_t fpsScale = getFPSScale(144.0); | |||
| 2551 | mpForegroundValue += fpsScale * (setpointDiff / 20.0); // reach it in 20 intervals, scaled to FPS | |||
| 2552 | } | |||
| 2553 | mpForegroundValue = std::min(static_cast<real_t>(MPBar.animateSetpoint), mpForegroundValue); | |||
| 2554 | ||||
| 2555 | /*if ( abs(MPBar.animateSetpoint) - abs(mpForegroundValue) <= 1.0 ) | |||
| 2556 | { | |||
| 2557 | mpForegroundValue = MPBar.animateSetpoint; | |||
| 2558 | }*/ | |||
| 2559 | } | |||
| 2560 | else if ( mpForegroundValue > MPBar.animateSetpoint ) // losing MP, snap to value | |||
| 2561 | { | |||
| 2562 | mpForegroundValue = MPBar.animateSetpoint; | |||
| 2563 | } | |||
| 2564 | ||||
| 2565 | if ( mpFadedValue < MPBar.animateSetpoint ) | |||
| 2566 | { | |||
| 2567 | mpFadedValue = mpForegroundValue; | |||
| 2568 | MPBar.animateTicks = ticks; | |||
| 2569 | } | |||
| 2570 | else if ( mpFadedValue > MPBar.animateSetpoint ) | |||
| 2571 | { | |||
| 2572 | if ( ticks - MPBar.animateTicks > 30 /*|| stats[player.playernum]->MP <= 0*/ ) // fall after x ticks | |||
| 2573 | { | |||
| 2574 | if ( doAnimation ) | |||
| 2575 | { | |||
| 2576 | real_t setpointDiff = std::max(0.1, mpFadedValue - MPBar.animateSetpoint); | |||
| 2577 | real_t fpsScale = getFPSScale(144.0); | |||
| 2578 | mpFadedValue -= fpsScale * (setpointDiff / 20.0); // reach it in 20 intervals, scaled to FPS | |||
| 2579 | } | |||
| 2580 | mpFadedValue = std::max(static_cast<real_t>(MPBar.animateSetpoint), mpFadedValue); | |||
| 2581 | } | |||
| 2582 | } | |||
| 2583 | else | |||
| 2584 | { | |||
| 2585 | MPBar.animateTicks = ticks; | |||
| 2586 | } | |||
| 2587 | ||||
| 2588 | real_t foregroundPercent = mpForegroundValue / MPBar.maxValue; | |||
| 2589 | mpProgress->pos.w = std::max(1, static_cast<int>((progressWidth)* foregroundPercent)); | |||
| 2590 | mpProgressEndcap->pos.x = mpProgress->pos.x + mpProgress->pos.w; | |||
| 2591 | ||||
| 2592 | auto mpProgressEndcapDamaged = mpFrame->findImage("mp img progress damaged"); | |||
| 2593 | mpProgressEndcapDamaged->disabled = true; | |||
| 2594 | mpProgressEndcapDamaged->pos.x = mpProgressEndcap->pos.x + (mpProgressEndcap->pos.w - mpProgressEndcapDamaged->pos.w); | |||
| 2595 | if ( mpForegroundValue < MPBar.maxValue ) // damaged | |||
| 2596 | { | |||
| 2597 | mpProgressEndcapDamaged->disabled = false; | |||
| 2598 | } | |||
| 2599 | ||||
| 2600 | real_t fadePercent = mpFadedValue / MPBar.maxValue; | |||
| 2601 | if ( MP <= 0 ) | |||
| 2602 | { | |||
| 2603 | // hide all the progress elements when dead, as endcap/base don't shrink | |||
| 2604 | // mpProgress width 0px defaults to original size, so hide that too | |||
| 2605 | mpProgress->disabled = true; | |||
| 2606 | mpProgressEndcap->disabled = true; | |||
| 2607 | mpProgressBase->disabled = true; | |||
| 2608 | mpProgressEndcapDamaged->disabled = true; | |||
| 2609 | } | |||
| 2610 | else | |||
| 2611 | { | |||
| 2612 | mpProgress->disabled = false; | |||
| 2613 | mpProgressEndcap->disabled = false; | |||
| 2614 | mpProgressBase->disabled = false; | |||
| 2615 | } | |||
| 2616 | ||||
| 2617 | auto mpProgressEndCapFlash = mpFrame->findImage("mp img progress endcap flash"); | |||
| 2618 | mpProgressEndCapFlash->disabled = true; | |||
| 2619 | const int framesPerAnimation = MPBar.flashType == Player::HUD_t::FLASH_ON_DAMAGE ? 1 : 2; | |||
| 2620 | const int numAnimationFrames = MPBar.flashType == Player::HUD_t::FLASH_ON_DAMAGE ? 30 : 2; | |||
| 2621 | if ( MPBar.flashTicks > 0 ) | |||
| 2622 | { | |||
| 2623 | //messagePlayer(0, MESSAGE_DEBUG, "ticks: %d, animticks: %d, state: %d", ticks, MPBarFlashTicks, MPBarFlashAnimState); | |||
| 2624 | if ( MPBar.flashAnimState > numAnimationFrames || mpProgress->disabled ) | |||
| 2625 | { | |||
| 2626 | MPBar.flashTicks = 0; | |||
| 2627 | MPBar.flashType = Player::HUD_t::FLASH_ON_DAMAGE; | |||
| 2628 | MPBar.flashAnimState = -1; | |||
| 2629 | mpProgressEndCapFlash->disabled = true; | |||
| 2630 | } | |||
| 2631 | else | |||
| 2632 | { | |||
| 2633 | mpProgressEndCapFlash->disabled = mpProgressEndcap->disabled; | |||
| 2634 | bool processedOnTick = MPBar.flashProcessedOnTick == ticks; | |||
| 2635 | if ( ticks == MPBar.flashTicks ) | |||
| 2636 | { | |||
| 2637 | MPBar.flashAnimState = 1; | |||
| 2638 | MPBar.flashProcessedOnTick = ticks; | |||
| 2639 | } | |||
| 2640 | else if ( (!processedOnTick) | |||
| 2641 | && (ticks > MPBar.flashTicks) | |||
| 2642 | && (ticks - MPBar.flashTicks) % framesPerAnimation == 0 ) | |||
| 2643 | { | |||
| 2644 | ++MPBar.flashAnimState; | |||
| 2645 | MPBar.flashProcessedOnTick = ticks; | |||
| 2646 | } | |||
| 2647 | ||||
| 2648 | if ( MPBar.flashType == Player::HUD_t::FLASH_ON_DAMAGE ) | |||
| 2649 | { | |||
| 2650 | if ( MPBar.flashAnimState <= 16 && MPBar.flashAnimState >= 10 ) | |||
| 2651 | { | |||
| 2652 | mpProgressEndCapFlash->color = 0xFFFFFFFF; | |||
| 2653 | } | |||
| 2654 | else if ( MPBar.flashAnimState == 0 ) | |||
| 2655 | { | |||
| 2656 | mpProgressEndCapFlash->color = makeColor(255, 255, 255, 0); | |||
| 2657 | mpProgressEndCapFlash->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_MPEnd_F00.png"; | |||
| 2658 | } | |||
| 2659 | ||||
| 2660 | if ( MPBar.flashAnimState <= 9 ) | |||
| 2661 | { | |||
| 2662 | if ( MPBar.flashAnimState == 7 ) | |||
| 2663 | { | |||
| 2664 | // we need the MP bar to flash long enough for long spellcast times | |||
| 2665 | // can adjust how many animStates we skip here to play with timing, | |||
| 2666 | // without changing other state machine code | |||
| 2667 | MPBar.flashAnimState = 9; // 1, 2 skip a few.. | |||
| 2668 | } | |||
| 2669 | Uint8 r, g, b, a; | |||
| 2670 | getColor(mpProgressEndCapFlash->color, &r, &g, &b, &a); | |||
| 2671 | int increment = 10; | |||
| 2672 | real_t fpsScale = getFPSScale(60.0); | |||
| 2673 | increment *= fpsScale; | |||
| 2674 | a = std::min(255, (int)a + increment); | |||
| 2675 | mpProgressEndCapFlash->color = makeColor(r, g, b, a); | |||
| 2676 | ||||
| 2677 | mpProgress->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Mid_00.png"; | |||
| 2678 | mpProgressBase->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_F00.png"; | |||
| 2679 | ||||
| 2680 | if ( MPBar.flashAnimState % 2 == 0 | |||
| 2681 | && !processedOnTick ) | |||
| 2682 | { | |||
| 2683 | mpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_F00.png"; | |||
| 2684 | } | |||
| 2685 | } | |||
| 2686 | else if ( MPBar.flashAnimState <= 10 ) | |||
| 2687 | { | |||
| 2688 | mpProgress->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Mid_00.png"; | |||
| 2689 | mpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_F00.png"; | |||
| 2690 | mpProgressBase->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Base_00.png"; | |||
| 2691 | } | |||
| 2692 | else if ( MPBar.flashAnimState >= 11 && MPBar.flashAnimState <= 12 ) | |||
| 2693 | { | |||
| 2694 | mpProgress->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Mid_01.png"; | |||
| 2695 | mpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_F01.png"; | |||
| 2696 | mpProgressBase->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Base_01.png"; | |||
| 2697 | } | |||
| 2698 | else if ( MPBar.flashAnimState == 13 ) | |||
| 2699 | { | |||
| 2700 | mpProgress->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Mid_02.png"; | |||
| 2701 | mpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_F02.png"; | |||
| 2702 | mpProgressBase->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Base_02.png"; | |||
| 2703 | } | |||
| 2704 | else if ( MPBar.flashAnimState >= 14 && MPBar.flashAnimState <= 15 ) | |||
| 2705 | { | |||
| 2706 | mpProgress->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Mid_01.png"; | |||
| 2707 | mpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_F01.png"; | |||
| 2708 | mpProgressBase->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Base_01.png"; | |||
| 2709 | } | |||
| 2710 | else if ( MPBar.flashAnimState == 16 ) | |||
| 2711 | { | |||
| 2712 | mpProgress->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Mid_03.png"; | |||
| 2713 | mpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_F03.png"; | |||
| 2714 | mpProgressBase->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Base_03.png"; | |||
| 2715 | } | |||
| 2716 | else | |||
| 2717 | { | |||
| 2718 | mpProgress->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Mid_00.png"; | |||
| 2719 | mpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_F00.png"; | |||
| 2720 | mpProgressBase->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Base_00.png"; | |||
| 2721 | Uint8 r, g, b, a; | |||
| 2722 | getColor(mpProgressEndCapFlash->color, &r, &g, &b, &a); | |||
| 2723 | int decrement = 20; | |||
| 2724 | real_t fpsScale = getFPSScale(60.0); | |||
| 2725 | decrement *= fpsScale; | |||
| 2726 | a = std::max(0, (int)a - decrement); | |||
| 2727 | mpProgressEndCapFlash->color = makeColor(r, g, b, a); | |||
| 2728 | } | |||
| 2729 | } | |||
| 2730 | else | |||
| 2731 | { | |||
| 2732 | mpProgressEndCapFlash->color = 0xFFFFFFFF; | |||
| 2733 | mpProgressEndCapFlash->disabled = true; | |||
| 2734 | if ( MPBar.flashAnimState == 1 ) | |||
| 2735 | { | |||
| 2736 | mpProgress->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Mid_03.png"; | |||
| 2737 | mpProgressBase->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Base_03.png"; | |||
| 2738 | mpProgressEndcap->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_03.png"; | |||
| 2739 | } | |||
| 2740 | } | |||
| 2741 | } | |||
| 2742 | } | |||
| 2743 | else | |||
| 2744 | { | |||
| 2745 | MPBar.flashAnimState = -1; | |||
| 2746 | mpProgress->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Mid_00.png"; | |||
| 2747 | mpProgressEndCapFlash->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_End_F00.png"; | |||
| 2748 | mpProgressBase->path = "*#images/ui/HUD/allies/HUD_MPBar_Fill_Base_00.png"; | |||
| 2749 | mpProgressEndCapFlash->disabled = true; | |||
| 2750 | } | |||
| 2751 | if ( !mpProgressEndcap->disabled ) | |||
| 2752 | { | |||
| 2753 | mpProgressEndCapFlash->pos.x = mpProgressEndcap->pos.x - (mpProgressEndCapFlash->pos.w - mpProgressEndcap->pos.w); | |||
| 2754 | } | |||
| 2755 | } | |||
| 2756 | followerBar.bInit = true; | |||
| 2757 | if ( followerBar.selected && !titleFrame ) | |||
| 2758 | { | |||
| 2759 | if ( selector ) | |||
| 2760 | { | |||
| 2761 | SDL_Color color; | |||
| 2762 | getColor(selector->color, &color.r, &color.g, &color.b, &color.a); | |||
| 2763 | selector->color = makeColor(color.r, color.g, color.b, 255 * entryFrame->getOpacity() / 100.0); | |||
| 2764 | selector->disabled = false; | |||
| 2765 | if ( auto imgGet = Image::get(selector->path.c_str()) ) | |||
| 2766 | { | |||
| 2767 | selector->pos.w = imgGet->getWidth(); | |||
| 2768 | selector->pos.h = imgGet->getHeight(); | |||
| 2769 | } | |||
| 2770 | selector->pos.x = entryFrame->getSize().x + selectorX - 8 - selector->pos.w; | |||
| 2771 | selector->pos.y = entryFrame->getSize().y + entryFrame->getSize().h / 2 - selector->pos.h / 2; | |||
| 2772 | } | |||
| 2773 | } | |||
| 2774 | else if ( followerBar.selected && titleFrame && updateTitleFrame ) | |||
| 2775 | { | |||
| 2776 | if ( titleSelector ) | |||
| 2777 | { | |||
| 2778 | SDL_Color color; | |||
| 2779 | getColor(titleSelector->color, &color.r, &color.g, &color.b, &color.a); | |||
| 2780 | titleSelector->color = makeColor(color.r, color.g, color.b, 255 * entryFrame->getOpacity() / 100.0); | |||
| 2781 | titleSelector->disabled = false; | |||
| 2782 | if ( auto imgGet = Image::get(titleSelector->path.c_str()) ) | |||
| 2783 | { | |||
| 2784 | titleSelector->pos.w = imgGet->getWidth(); | |||
| 2785 | titleSelector->pos.h = imgGet->getHeight(); | |||
| 2786 | } | |||
| 2787 | titleSelector->pos.y = entryFrame->getSize().y + entryFrame->getSize().h / 2 - titleSelector->pos.h / 2; | |||
| 2788 | titleSelector->pos.x = entryFrame->getSize().x + selectorX - titleSelector->pos.w; | |||
| 2789 | const int selectorAnimW = 4; | |||
| 2790 | if ( titleSelectorGlyph ) | |||
| 2791 | { | |||
| 2792 | if ( halfWidthBars | |||
| 2793 | || (!players[player]->shootmode && !FollowerMenu[player].followerMenuIsOpen() && !CalloutMenu[player].calloutMenuIsOpen()) | |||
| 2794 | || followerDisplay.bCycleNextDisabled || list_Size(&stats[player]->FOLLOWERS) <= 1 ) | |||
| 2795 | { | |||
| 2796 | titleSelectorGlyph->disabled = true; | |||
| 2797 | } | |||
| 2798 | else | |||
| 2799 | { | |||
| 2800 | titleSelectorGlyph->path = Input::inputs[player].getGlyphPathForBinding("Cycle NPCs"); | |||
| 2801 | if ( auto imgGet = Image::get(titleSelectorGlyph->path.c_str()) ) | |||
| 2802 | { | |||
| 2803 | titleSelectorGlyph->disabled = false; | |||
| 2804 | titleSelectorGlyph->pos.w = imgGet->getWidth(); | |||
| 2805 | titleSelectorGlyph->pos.h = imgGet->getHeight(); | |||
| 2806 | titleSelectorGlyph->pos.x = titleSelector->pos.x - 2 * selectorAnimW - titleSelectorGlyph->pos.w; | |||
| 2807 | titleSelectorGlyph->pos.y = titleSelector->pos.y + titleSelector->pos.h / 2 - titleSelectorGlyph->pos.h / 2; | |||
| 2808 | ||||
| 2809 | static ConsoleVariable<int> followerMenuOpenGlyphX("/followermenu_open_glyph_x", 6); | |||
| 2810 | static ConsoleVariable<int> followerMenuOpenGlyphY("/followermenu_open_glyph_y", 0); | |||
| 2811 | titleSelectorGlyph->pos.x += *followerMenuOpenGlyphX; | |||
| 2812 | titleSelectorGlyph->pos.y += *followerMenuOpenGlyphY; | |||
| 2813 | if ( titleSelectorGlyph->pos.y % 2 == 1 ) | |||
| 2814 | { | |||
| 2815 | --titleSelectorGlyph->pos.y; | |||
| 2816 | } | |||
| 2817 | } | |||
| 2818 | } | |||
| 2819 | } | |||
| 2820 | ||||
| 2821 | titleSelector->pos.x += 4 - selectorAnimW * (cos(followerDisplay.animSelected * 2 * PI3.14159265358979323846)); | |||
| 2822 | } | |||
| 2823 | } | |||
| 2824 | ||||
| 2825 | if ( followerBar.selected && titleFrame && !doneTitleFrame ) | |||
| 2826 | { | |||
| 2827 | updateTitleFrame = true; | |||
| 2828 | --barIndex; | |||
| 2829 | } | |||
| 2830 | else | |||
| 2831 | { | |||
| 2832 | updateTitleFrame = false; | |||
| 2833 | ++it; | |||
| 2834 | } | |||
| 2835 | } | |||
| 2836 | ||||
| 2837 | followerDisplay.bHalfWidthBars = halfWidthBars; | |||
| 2838 | ||||
| 2839 | SDL_Rect baseFramePos = baseFrame->getSize(); | |||
| 2840 | baseFramePos.h = baseFrameHeight; | |||
| 2841 | baseFrame->setSize(baseFramePos); | |||
| 2842 | baseFrame->setActualSize(SDL_Rect{ | |||
| 2843 | baseFrame->getActualSize().x, | |||
| 2844 | baseFrame->getActualSize().y, | |||
| 2845 | baseFrame->getActualSize().w , | |||
| 2846 | infiniteScrolling ? baseFramePos.h * 10 : currentY }); | |||
| 2847 | ||||
| 2848 | ||||
| 2849 | if ( !bPlayerBars && titleFrame && hud_t.allyFollowerGlyphFrame && !hud_t.allyFollowerGlyphFrame->isDisabled() ) | |||
| 2850 | { | |||
| 2851 | static ConsoleVariable<int> followerMenuCommandGlyphX("/followermenu_cmd_glyph_x", -96); | |||
| 2852 | static ConsoleVariable<int> followerMenuCommandGlyphY("/followermenu_cmd_glyph_y", 0); | |||
| 2853 | static ConsoleVariable<int> followerMenuRepeatGlyphX("/followermenu_repeat_glyph_x", 0); | |||
| 2854 | static ConsoleVariable<int> followerMenuRepeatGlyphY("/followermenu_repeat_glyph_y", 0); | |||
| 2855 | ||||
| 2856 | auto glyphFrame = hud_t.allyFollowerGlyphFrame; | |||
| 2857 | SDL_Rect glyphFramePos{ baseFrame->getSize().x, titleFrame->getSize().y, 150, 80 }; | |||
| 2858 | glyphFramePos.x += *followerMenuCommandGlyphX; | |||
| 2859 | if ( !titleSelectorGlyph->disabled ) | |||
| 2860 | { | |||
| 2861 | glyphFramePos.x -= titleSelectorGlyph->pos.w; | |||
| 2862 | } | |||
| 2863 | glyphFramePos.y += *followerMenuCommandGlyphY; | |||
| 2864 | glyphFrame->setSize(glyphFramePos); | |||
| 2865 | ||||
| 2866 | auto commandGlyph = glyphFrame->findImage("glyph command"); | |||
| 2867 | auto commandImg = glyphFrame->findImage("img command"); | |||
| 2868 | //auto commandText = glyphFrame->findField("command prompt txt"); | |||
| 2869 | ||||
| 2870 | auto repeatGlyph = glyphFrame->findImage("glyph repeat"); | |||
| 2871 | auto repeatImg = glyphFrame->findImage("img repeat"); | |||
| 2872 | //auto repeatCmdText = glyphFrame->findField("repeat prompt txt"); | |||
| 2873 | ||||
| 2874 | if ( auto imgGet = Image::get(commandImg->path.c_str()) ) | |||
| 2875 | { | |||
| 2876 | commandImg->disabled = false; | |||
| 2877 | commandImg->pos.w = imgGet->getWidth(); | |||
| 2878 | commandImg->pos.h = imgGet->getHeight(); | |||
| 2879 | commandImg->pos.x = glyphFramePos.w - commandImg->pos.w; | |||
| 2880 | commandImg->pos.y = 0; | |||
| 2881 | ||||
| 2882 | commandGlyph->path = Input::inputs[player].getGlyphPathForBinding("Show NPC Commands"); | |||
| 2883 | if ( auto imgGet = Image::get(commandGlyph->path.c_str()) ) | |||
| 2884 | { | |||
| 2885 | commandGlyph->disabled = commandImg->disabled || followerDisplay.bOpenFollowerMenuDisabled; | |||
| 2886 | commandGlyph->pos.w = imgGet->getWidth(); | |||
| 2887 | commandGlyph->pos.h = imgGet->getHeight(); | |||
| 2888 | commandGlyph->pos.x = commandImg->pos.x - commandGlyph->pos.w; | |||
| 2889 | commandGlyph->pos.y = commandImg->pos.y + commandImg->pos.h / 2 - commandGlyph->pos.h / 2; | |||
| 2890 | } | |||
| 2891 | else | |||
| 2892 | { | |||
| 2893 | commandImg->disabled = true; | |||
| 2894 | commandGlyph->disabled = true; | |||
| 2895 | } | |||
| 2896 | } | |||
| 2897 | ||||
| 2898 | if ( FollowerMenu[player].optionPrevious == -1 ) | |||
| 2899 | { | |||
| 2900 | repeatImg->disabled = true; | |||
| 2901 | repeatGlyph->disabled = true; | |||
| 2902 | } | |||
| 2903 | else | |||
| 2904 | { | |||
| 2905 | if ( auto imgGet = Image::get(repeatImg->path.c_str()) ) | |||
| 2906 | { | |||
| 2907 | repeatImg->disabled = false; | |||
| 2908 | repeatImg->pos.w = imgGet->getWidth(); | |||
| 2909 | repeatImg->pos.h = imgGet->getHeight(); | |||
| 2910 | if ( commandImg->disabled ) | |||
| 2911 | { | |||
| 2912 | repeatImg->pos.x = commandImg->pos.x - repeatImg->pos.w + *followerMenuRepeatGlyphX; | |||
| 2913 | } | |||
| 2914 | else | |||
| 2915 | { | |||
| 2916 | repeatImg->pos.x = commandGlyph->pos.x - repeatImg->pos.w + *followerMenuRepeatGlyphX; | |||
| 2917 | } | |||
| 2918 | repeatImg->pos.y = commandImg->pos.y + commandImg->pos.h / 2 - repeatImg->pos.h / 2 + *followerMenuRepeatGlyphY; | |||
| 2919 | } | |||
| 2920 | repeatGlyph->path = Input::inputs[player].getGlyphPathForBinding("Command NPC"); | |||
| 2921 | if ( auto imgGet = Image::get(repeatGlyph->path.c_str()) ) | |||
| 2922 | { | |||
| 2923 | repeatGlyph->disabled = repeatImg->disabled || followerDisplay.bCommandNPCDisabled; | |||
| 2924 | repeatGlyph->pos.w = imgGet->getWidth(); | |||
| 2925 | repeatGlyph->pos.h = imgGet->getHeight(); | |||
| 2926 | repeatGlyph->pos.x = repeatImg->pos.x - repeatGlyph->pos.w; | |||
| 2927 | repeatGlyph->pos.y = repeatImg->pos.y + repeatImg->pos.h / 2 - repeatGlyph->pos.h / 2; | |||
| 2928 | } | |||
| 2929 | else | |||
| 2930 | { | |||
| 2931 | repeatImg->disabled = true; | |||
| 2932 | repeatGlyph->disabled = true; | |||
| 2933 | } | |||
| 2934 | } | |||
| 2935 | } | |||
| 2936 | } | |||
| 2937 | ||||
| 2938 | void updateAllyFollowerFrame(const int player) | |||
| 2939 | { | |||
| 2940 | if ( !players[player]->hud.allyFollowerFrame ) | |||
| 2941 | { | |||
| 2942 | return; | |||
| 2943 | } | |||
| 2944 | ||||
| 2945 | auto& hud_t = players[player]->hud; | |||
| 2946 | Frame* baseFrame = hud_t.allyFollowerFrame; | |||
| 2947 | Frame* titleFrame = hud_t.allyFollowerTitleFrame; | |||
| 2948 | Frame* glyphFrame = hud_t.allyFollowerGlyphFrame; | |||
| 2949 | ||||
| 2950 | static ConsoleVariable<bool> cvar_followerbars("/followerbars", true); | |||
| 2951 | ||||
| 2952 | if ( !players[player]->isLocalPlayer() || !(*cvar_followerbars) ) | |||
| 2953 | { | |||
| 2954 | baseFrame->setDisabled(true); | |||
| 2955 | titleFrame->setDisabled(true); | |||
| 2956 | glyphFrame->setDisabled(true); | |||
| 2957 | return; | |||
| 2958 | } | |||
| 2959 | ||||
| 2960 | if ( !players[player]->shootmode && !FollowerMenu[player].followerMenuIsOpen() | |||
| 2961 | && !CalloutMenu[player].calloutMenuIsOpen() | |||
| 2962 | && players[player]->gui_mode != GUI_MODE_NONE ) | |||
| 2963 | { | |||
| 2964 | baseFrame->setOpacity(0.0); | |||
| 2965 | baseFrame->setInheritParentFrameOpacity(false); | |||
| 2966 | } | |||
| 2967 | else | |||
| 2968 | { | |||
| 2969 | baseFrame->setInheritParentFrameOpacity(true); | |||
| 2970 | baseFrame->setOpacity(baseFrame->getParent()->getOpacity()); | |||
| 2971 | } | |||
| 2972 | ||||
| 2973 | auto& infiniteScrolling = Player::HUD_t::FollowerDisplay_t::infiniteScrolling; | |||
| 2974 | ||||
| 2975 | baseFrame->setDisabled(false); | |||
| 2976 | SDL_Rect baseFramePos = baseFrame->getSize(); | |||
| 2977 | baseFramePos.x = hud_t.hudFrame->getSize().w - baseFramePos.w; | |||
| 2978 | const int baseY = baseFramePos.y = players[player]->bUseCompactGUIWidth() ? AllyStatusBarSettings_t::FollowerBars_t::entrySettings.baseYSplitscreen : AllyStatusBarSettings_t::FollowerBars_t::entrySettings.baseY; | |||
| 2979 | baseFramePos.y = baseY + (infiniteScrolling ? AllyStatusBarSettings_t::FollowerBars_t::entrySettings.entryHeight : 0); | |||
| 2980 | baseFrame->setSize(baseFramePos); | |||
| 2981 | ||||
| 2982 | titleFrame->setDisabled(true); | |||
| 2983 | glyphFrame->setDisabled(true); | |||
| 2984 | if ( infiniteScrolling ) | |||
| 2985 | { | |||
| 2986 | titleFrame->setSize(SDL_Rect{ baseFramePos.x, 0, baseFramePos.w, baseY + 2 * AllyStatusBarSettings_t::FollowerBars_t::entrySettings.entryHeight }); | |||
| 2987 | titleFrame->setDisabled(false); | |||
| 2988 | } | |||
| 2989 | ||||
| 2990 | /*if ( enableDebugKeys && keystatus[SDLK_H] ) | |||
| 2991 | { | |||
| 2992 | keystatus[SDLK_H] = 0; | |||
| 2993 | hud_t.followerBars.push_back(std::make_pair(0, Player::HUD_t::FollowerBar_t())); | |||
| 2994 | } | |||
| 2995 | ||||
| 2996 | if ( enableDebugKeys && keystatus[SDLK_J] ) | |||
| 2997 | { | |||
| 2998 | keystatus[SDLK_J] = 0; | |||
| 2999 | if ( hud_t.followerBars.size() > 0 ) | |||
| 3000 | { | |||
| 3001 | auto it = hud_t.followerBars.begin() + local_rng.rand() % hud_t.followerBars.size(); | |||
| 3002 | it->second.expired = true; | |||
| 3003 | } | |||
| 3004 | }*/ | |||
| 3005 | ||||
| 3006 | std::vector<Uint32> sortedUids; | |||
| 3007 | for ( node_t* node = stats[player]->FOLLOWERS.first; node != nullptr; node = node->next ) | |||
| 3008 | { | |||
| 3009 | Entity* follower = nullptr; | |||
| 3010 | if ( (Uint32*)node->element ) | |||
| 3011 | { | |||
| 3012 | follower = uidToEntity(*((Uint32*)node->element)); | |||
| 3013 | sortedUids.push_back(*((Uint32*)node->element)); | |||
| 3014 | } | |||
| 3015 | if ( follower ) | |||
| 3016 | { | |||
| 3017 | Uint32 uid = follower->getUID(); | |||
| 3018 | auto it = std::find_if(hud_t.followerBars.begin(), hud_t.followerBars.end(), | |||
| 3019 | [&uid](const std::pair<Uint32, Player::HUD_t::FollowerBar_t>& bar) | |||
| 3020 | { | |||
| 3021 | return bar.first == uid && !bar.second.expired; | |||
| 3022 | }); | |||
| 3023 | if ( it == hud_t.followerBars.end() ) | |||
| 3024 | { | |||
| 3025 | hud_t.followerBars.push_back(std::make_pair(uid, Player::HUD_t::FollowerBar_t())); | |||
| 3026 | auto& bar = hud_t.followerBars.at(hud_t.followerBars.size() - 1); | |||
| 3027 | bar.second.animFadeScroll = 1.0; | |||
| 3028 | bar.second.animFadeScrollDummy = 1.0; | |||
| 3029 | } | |||
| 3030 | } | |||
| 3031 | } | |||
| 3032 | ||||
| 3033 | int activeBars = 0; | |||
| 3034 | int realActiveBars = 0; | |||
| 3035 | bool erasedEntry = false; | |||
| 3036 | for ( auto it = hud_t.followerBars.begin(); it != hud_t.followerBars.end(); ) | |||
| 3037 | { | |||
| 3038 | if ( it->second.dummy ) | |||
| 3039 | { | |||
| 3040 | it = hud_t.followerBars.erase(it); | |||
| 3041 | } | |||
| 3042 | else if ( it->second.expired && it->second.animy >= 0.999 ) | |||
| 3043 | { | |||
| 3044 | it = hud_t.followerBars.erase(it); | |||
| 3045 | erasedEntry = true; | |||
| 3046 | } | |||
| 3047 | else | |||
| 3048 | { | |||
| 3049 | ++activeBars; | |||
| 3050 | ++realActiveBars; | |||
| 3051 | ++it; | |||
| 3052 | } | |||
| 3053 | } | |||
| 3054 | ||||
| 3055 | auto& followerDisplay = hud_t.followerDisplay; | |||
| 3056 | if ( !FollowerMenu[player].recentEntity ) | |||
| 3057 | { | |||
| 3058 | // try find a new follower within the visible list | |||
| 3059 | const int kNumEntriesToShow = Player::HUD_t::FollowerDisplay_t::getNumEntriesToShow(player); | |||
| 3060 | if ( infiniteScrolling ) | |||
| 3061 | { | |||
| 3062 | int index = 0; | |||
| 3063 | for ( auto& pair : hud_t.followerBars ) | |||
| 3064 | { | |||
| 3065 | if ( index >= followerDisplay.scrollSetpoint && index < kNumEntriesToShow ) | |||
| 3066 | { | |||
| 3067 | if ( Entity* follower = uidToEntity(pair.first) ) | |||
| 3068 | { | |||
| 3069 | // check is valid follower in list | |||
| 3070 | if ( std::find(sortedUids.begin(), sortedUids.end(), pair.first) != sortedUids.end() ) | |||
| 3071 | { | |||
| 3072 | FollowerMenu[player].recentEntity = follower; | |||
| 3073 | break; | |||
| 3074 | } | |||
| 3075 | } | |||
| 3076 | } | |||
| 3077 | ++index; | |||
| 3078 | } | |||
| 3079 | } | |||
| 3080 | else if ( hud_t.followerBars.size() > kNumEntriesToShow ) | |||
| 3081 | { | |||
| 3082 | int index = 0; | |||
| 3083 | for ( auto& pair : hud_t.followerBars ) | |||
| 3084 | { | |||
| 3085 | if ( index >= followerDisplay.scrollSetpoint | |||
| 3086 | && index < (followerDisplay.scrollSetpoint + kNumEntriesToShow) ) | |||
| 3087 | { | |||
| 3088 | if ( Entity* follower = uidToEntity(pair.first) ) | |||
| 3089 | { | |||
| 3090 | // check is valid follower in list | |||
| 3091 | if ( std::find(sortedUids.begin(), sortedUids.end(), pair.first) != sortedUids.end() ) | |||
| 3092 | { | |||
| 3093 | FollowerMenu[player].recentEntity = follower; | |||
| 3094 | break; | |||
| 3095 | } | |||
| 3096 | } | |||
| 3097 | } | |||
| 3098 | ++index; | |||
| 3099 | } | |||
| 3100 | } | |||
| 3101 | ||||
| 3102 | if ( !FollowerMenu[player].recentEntity ) // find the first one if nothing found before | |||
| 3103 | { | |||
| 3104 | for ( auto& pair : hud_t.followerBars ) | |||
| 3105 | { | |||
| 3106 | if ( Entity* follower = uidToEntity(pair.first) ) | |||
| 3107 | { | |||
| 3108 | // check is valid follower in list | |||
| 3109 | if ( std::find(sortedUids.begin(), sortedUids.end(), pair.first) != sortedUids.end() ) | |||
| 3110 | { | |||
| 3111 | FollowerMenu[player].recentEntity = follower; | |||
| 3112 | break; | |||
| 3113 | } | |||
| 3114 | } | |||
| 3115 | } | |||
| 3116 | } | |||
| 3117 | } | |||
| 3118 | ||||
| 3119 | bool selectedFollower = false; | |||
| 3120 | Uint32 recentFollowerUID = FollowerMenu[player].recentEntity ? FollowerMenu[player].recentEntity->getUID() : 0; | |||
| 3121 | { | |||
| 3122 | int index = 0; | |||
| 3123 | for ( auto& pair : hud_t.followerBars ) | |||
| 3124 | { | |||
| 3125 | pair.second.selected = false; | |||
| 3126 | if ( FollowerMenu[player].recentEntity ) | |||
| 3127 | { | |||
| 3128 | if ( !selectedFollower && recentFollowerUID != 0 && pair.first == recentFollowerUID ) | |||
| 3129 | { | |||
| 3130 | pair.second.selected = true; | |||
| 3131 | selectedFollower = true; | |||
| 3132 | if ( infiniteScrolling && erasedEntry ) | |||
| 3133 | { | |||
| 3134 | // one-off check on deletion, need to snap the scroll to desired location. | |||
| 3135 | // otherwise, causes unneccessary scrolling for nothing as index is outdated. | |||
| 3136 | if ( followerDisplay.scrollSetpoint > (index + 1) ) | |||
| 3137 | { | |||
| 3138 | followerDisplay.scrollSetpoint = index + 1; | |||
| 3139 | followerDisplay.scrollAnimateX = followerDisplay.scrollSetpoint; | |||
| 3140 | } | |||
| 3141 | } | |||
| 3142 | } | |||
| 3143 | } | |||
| 3144 | ++index; | |||
| 3145 | } | |||
| 3146 | } | |||
| 3147 | ||||
| 3148 | if ( selectedFollower && (players[player]->shootmode || FollowerMenu[player].followerMenuIsOpen()) && | |||
| 3149 | list_Size(&stats[player]->FOLLOWERS) > 0 && !players[player]->bUseCompactGUIWidth() ) | |||
| 3150 | { | |||
| 3151 | glyphFrame->setDisabled(false); | |||
| 3152 | } | |||
| 3153 | ||||
| 3154 | if ( !FollowerMenu[player].recentEntity ) | |||
| 3155 | { | |||
| 3156 | followerDisplay.lastUidSelected = 0; | |||
| 3157 | followerDisplay.animSelected = 0.0; | |||
| 3158 | } | |||
| 3159 | else | |||
| 3160 | { | |||
| 3161 | if ( followerDisplay.lastUidSelected != recentFollowerUID ) | |||
| 3162 | { | |||
| 3163 | followerDisplay.animSelected = 1.0; | |||
| 3164 | followerDisplay.scrollTicks = ticks; | |||
| 3165 | } | |||
| 3166 | followerDisplay.lastUidSelected = recentFollowerUID; | |||
| 3167 | } | |||
| 3168 | ||||
| 3169 | { | |||
| 3170 | size_t position = 0; | |||
| 3171 | for ( Uint32 uid : sortedUids ) // sort the displayed list to match the stats->FOLLOWERS list order | |||
| 3172 | { | |||
| 3173 | if ( position < hud_t.followerBars.size() ) | |||
| 3174 | { | |||
| 3175 | auto it2 = std::find(sortedUids.begin(), sortedUids.end(), hud_t.followerBars.at(position).first); | |||
| 3176 | if ( it2 == sortedUids.end() ) | |||
| 3177 | { | |||
| 3178 | // this bar isn't in the follower list and expired, skip position to sort | |||
| 3179 | ++position; | |||
| 3180 | } | |||
| 3181 | } | |||
| 3182 | ||||
| 3183 | auto it = std::find_if(hud_t.followerBars.begin() + position, hud_t.followerBars.end(), | |||
| 3184 | [uid](std::pair<Uint32, Player::HUD_t::FollowerBar_t>& pair) { | |||
| 3185 | return pair.first == uid; | |||
| 3186 | }); | |||
| 3187 | ||||
| 3188 | while ( it != hud_t.followerBars.end() ) | |||
| 3189 | { | |||
| 3190 | std::iter_swap(hud_t.followerBars.begin() + position, it); | |||
| 3191 | ++position; | |||
| 3192 | ||||
| 3193 | if ( position < hud_t.followerBars.size() ) | |||
| 3194 | { | |||
| 3195 | auto it2 = std::find(sortedUids.begin(), sortedUids.end(), hud_t.followerBars.at(position).first); | |||
| 3196 | if ( it2 == sortedUids.end() ) | |||
| 3197 | { | |||
| 3198 | // this bar isn't in the follower list and expired, skip position to sort | |||
| 3199 | ++position; | |||
| 3200 | } | |||
| 3201 | } | |||
| 3202 | ||||
| 3203 | it = std::find_if(hud_t.followerBars.begin() + position, hud_t.followerBars.end(), | |||
| 3204 | [uid](std::pair<Uint32, Player::HUD_t::FollowerBar_t>& pair) { | |||
| 3205 | return pair.first == uid; | |||
| 3206 | }); | |||
| 3207 | ||||
| 3208 | } | |||
| 3209 | } | |||
| 3210 | ||||
| 3211 | if ( infiniteScrolling ) | |||
| 3212 | { | |||
| 3213 | int barIndex = -1; | |||
| 3214 | size_t vecIndex = 0; | |||
| 3215 | while ( vecIndex < hud_t.followerBars.size() ) | |||
| 3216 | { | |||
| 3217 | ++barIndex; | |||
| 3218 | if ( hud_t.followerBars[vecIndex].second.dummy ) | |||
| 3219 | { | |||
| 3220 | break; | |||
| 3221 | } | |||
| 3222 | if ( barIndex < (followerDisplay.scrollSetpoint - 1) ) | |||
| 3223 | { | |||
| 3224 | hud_t.followerBars.push_back(hud_t.followerBars[vecIndex]); | |||
| 3225 | hud_t.followerBars[hud_t.followerBars.size() - 1].second.dummy = true; | |||
| 3226 | //messagePlayer(0, MESSAGE_DEBUG, "%.2f", hud_t.followerBars[hud_t.followerBars.size() - 1].second.animFadeScrollDummy); | |||
| 3227 | //hud_t.followerBars[hud_t.followerBars.size() - 1].second.animFadeScroll = 0.0; | |||
| 3228 | ++activeBars; | |||
| 3229 | } | |||
| 3230 | ++vecIndex; | |||
| 3231 | } | |||
| 3232 | } | |||
| 3233 | } | |||
| 3234 | ||||
| 3235 | followerDisplay.bCompact = followerDisplay.getCompactMode(player); | |||
| 3236 | ||||
| 3237 | updateAllyBarFrame(player, baseFrame, activeBars, realActiveBars, false); | |||
| 3238 | ||||
| 3239 | { | |||
| 3240 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 3241 | real_t setpointDiffX = fpsScale * 1.0 / 10.0; | |||
| 3242 | followerDisplay.animSelected -= setpointDiffX; | |||
| 3243 | followerDisplay.animSelected = std::max(0.0, followerDisplay.animSelected); | |||
| 3244 | } | |||
| 3245 | ||||
| 3246 | const int kNumEntriesToShow = Player::HUD_t::FollowerDisplay_t::getNumEntriesToShow(player); | |||
| 3247 | ||||
| 3248 | // scroll | |||
| 3249 | { | |||
| 3250 | int scrollAmount = 0; | |||
| 3251 | if ( infiniteScrolling ) | |||
| 3252 | { | |||
| 3253 | scrollAmount = hud_t.followerBars.size(); | |||
| 3254 | } | |||
| 3255 | else if ( hud_t.followerBars.size() > kNumEntriesToShow ) | |||
| 3256 | { | |||
| 3257 | scrollAmount = (hud_t.followerBars.size() - kNumEntriesToShow); | |||
| 3258 | } | |||
| 3259 | int oldSetpoint = followerDisplay.scrollSetpoint; | |||
| 3260 | if ( scrollAmount > 0 ) | |||
| 3261 | { | |||
| 3262 | int index = 0; | |||
| 3263 | bool foundSelected = false; | |||
| 3264 | for ( auto& pair : hud_t.followerBars ) | |||
| 3265 | { | |||
| 3266 | if ( pair.second.selected ) | |||
| 3267 | { | |||
| 3268 | foundSelected = true; | |||
| 3269 | if ( infiniteScrolling ) | |||
| 3270 | { | |||
| 3271 | followerDisplay.scrollSetpoint = index + 1; | |||
| 3272 | break; | |||
| 3273 | } | |||
| 3274 | ||||
| 3275 | if ( index < followerDisplay.scrollSetpoint ) | |||
| 3276 | { | |||
| 3277 | followerDisplay.scrollSetpoint = index; | |||
| 3278 | } | |||
| 3279 | else if ( index >= (followerDisplay.scrollSetpoint + kNumEntriesToShow) ) | |||
| 3280 | { | |||
| 3281 | while ( index >= (followerDisplay.scrollSetpoint + kNumEntriesToShow) ) | |||
| 3282 | { | |||
| 3283 | followerDisplay.scrollSetpoint += 1; | |||
| 3284 | } | |||
| 3285 | } | |||
| 3286 | break; | |||
| 3287 | } | |||
| 3288 | ++index; | |||
| 3289 | } | |||
| 3290 | ||||
| 3291 | if ( !foundSelected ) | |||
| 3292 | { | |||
| 3293 | followerDisplay.scrollSetpoint = 0; | |||
| 3294 | followerDisplay.scrollAnimateX = followerDisplay.scrollSetpoint; | |||
| 3295 | } | |||
| 3296 | } | |||
| 3297 | else | |||
| 3298 | { | |||
| 3299 | followerDisplay.scrollSetpoint = 0; | |||
| 3300 | } | |||
| 3301 | ||||
| 3302 | followerDisplay.scrollSetpoint = std::min(followerDisplay.scrollSetpoint, scrollAmount); | |||
| 3303 | followerDisplay.currentScrollRow = followerDisplay.scrollSetpoint; | |||
| 3304 | ||||
| 3305 | if ( abs(followerDisplay.scrollSetpoint - followerDisplay.scrollAnimateX) > 0.00001 ) | |||
| 3306 | { | |||
| 3307 | if ( infiniteScrolling ) | |||
| 3308 | { | |||
| 3309 | if ( followerDisplay.scrollSetpoint < followerDisplay.scrollAnimateX ) | |||
| 3310 | { | |||
| 3311 | realActiveBars += std::max(0, followerDisplay.scrollSetpoint - 1); // don't delete as many if setpoint > 1 | |||
| 3312 | followerDisplay.scrollAnimateX = followerDisplay.scrollSetpoint - 1; | |||
| 3313 | ||||
| 3314 | int index = 0; | |||
| 3315 | std::vector<real_t> oldAnimFadeScrolls; | |||
| 3316 | for ( auto& pair : hud_t.followerBars ) | |||
| 3317 | { | |||
| 3318 | if ( index >= oldSetpoint ) | |||
| 3319 | { | |||
| 3320 | oldAnimFadeScrolls.push_back(pair.second.dummy ? pair.second.animFadeScrollDummy : pair.second.animFadeScroll); | |||
| 3321 | } | |||
| 3322 | ++index; | |||
| 3323 | } | |||
| 3324 | index = 0; | |||
| 3325 | for ( auto& pair : hud_t.followerBars ) | |||
| 3326 | { | |||
| 3327 | if ( oldAnimFadeScrolls.size() > 0 ) | |||
| 3328 | { | |||
| 3329 | if ( pair.second.dummy ) | |||
| 3330 | { | |||
| 3331 | pair.second.animFadeScrollDummy = oldAnimFadeScrolls[0]; | |||
| 3332 | } | |||
| 3333 | else | |||
| 3334 | { | |||
| 3335 | pair.second.animFadeScroll = oldAnimFadeScrolls[0]; | |||
| 3336 | } | |||
| 3337 | oldAnimFadeScrolls.erase(oldAnimFadeScrolls.begin()); | |||
| 3338 | } | |||
| 3339 | ++index; | |||
| 3340 | } | |||
| 3341 | ||||
| 3342 | for ( int i = 0; i < realActiveBars; ++i ) | |||
| 3343 | { | |||
| 3344 | if ( i + (realActiveBars - 1) < baseFrame->getFrames().size() ) | |||
| 3345 | { | |||
| 3346 | baseFrame->getFrames()[i]->setOpacity(baseFrame->getFrames()[i + (realActiveBars - 1)]->getOpacity()); | |||
| 3347 | } | |||
| 3348 | } | |||
| 3349 | ||||
| 3350 | for ( auto f : baseFrame->getFrames() ) | |||
| 3351 | { | |||
| 3352 | if ( strcmp(f->getName(), "entry") || f->isToBeDeleted() ) | |||
| 3353 | { | |||
| 3354 | continue; | |||
| 3355 | } | |||
| 3356 | --realActiveBars; | |||
| 3357 | if ( realActiveBars <= 0 ) | |||
| 3358 | { | |||
| 3359 | f->removeSelf(); | |||
| 3360 | } | |||
| 3361 | } | |||
| 3362 | } | |||
| 3363 | } | |||
| 3364 | ||||
| 3365 | followerDisplay.isInteractable = false; | |||
| 3366 | const real_t fpsScale = getFPSScale(60.0); | |||
| 3367 | real_t setpointDiff = 0.0; | |||
| 3368 | const real_t scrollSpeed = 3.0; | |||
| 3369 | if ( followerDisplay.scrollSetpoint - followerDisplay.scrollAnimateX > 0.0 ) | |||
| 3370 | { | |||
| 3371 | real_t mult = 8.0; | |||
| 3372 | if ( ticks - followerDisplay.scrollTicks < TICKS_PER_SECOND50 ) | |||
| 3373 | { | |||
| 3374 | mult *= (ticks - followerDisplay.scrollTicks) / (real_t)(TICKS_PER_SECOND50); | |||
| 3375 | } | |||
| 3376 | mult = fmin(mult, 1.0); | |||
| 3377 | ||||
| 3378 | setpointDiff = mult * fpsScale * std::max(.03, (followerDisplay.scrollSetpoint - followerDisplay.scrollAnimateX)) / scrollSpeed; | |||
| 3379 | } | |||
| 3380 | else | |||
| 3381 | { | |||
| 3382 | real_t mult = 8.0; | |||
| 3383 | if ( ticks - followerDisplay.scrollTicks < TICKS_PER_SECOND50 ) | |||
| 3384 | { | |||
| 3385 | mult *= (ticks - followerDisplay.scrollTicks) / (real_t)(TICKS_PER_SECOND50); | |||
| 3386 | } | |||
| 3387 | mult = fmin(mult, 1.0); | |||
| 3388 | ||||
| 3389 | setpointDiff = mult * fpsScale * std::min(-.03, (followerDisplay.scrollSetpoint - followerDisplay.scrollAnimateX)) / scrollSpeed; | |||
| 3390 | } | |||
| 3391 | followerDisplay.scrollAnimateX += setpointDiff; | |||
| 3392 | if ( setpointDiff >= 0.0 ) | |||
| 3393 | { | |||
| 3394 | followerDisplay.scrollAnimateX = std::min((real_t)followerDisplay.scrollSetpoint, followerDisplay.scrollAnimateX); | |||
| 3395 | } | |||
| 3396 | else | |||
| 3397 | { | |||
| 3398 | followerDisplay.scrollAnimateX = std::max((real_t)followerDisplay.scrollSetpoint, followerDisplay.scrollAnimateX); | |||
| 3399 | } | |||
| 3400 | } | |||
| 3401 | else | |||
| 3402 | { | |||
| 3403 | followerDisplay.scrollAnimateX = followerDisplay.scrollSetpoint; | |||
| 3404 | } | |||
| 3405 | ||||
| 3406 | int scrollHeight = 0; | |||
| 3407 | real_t scrollRemaining = followerDisplay.scrollAnimateX; | |||
| 3408 | bool scrollingCompleted = false; | |||
| 3409 | for ( auto f : baseFrame->getFrames() ) | |||
| 3410 | { | |||
| 3411 | if ( strcmp(f->getName(), "entry") || f->isToBeDeleted() ) | |||
| 3412 | { | |||
| 3413 | continue; | |||
| 3414 | } | |||
| 3415 | ||||
| 3416 | if ( !scrollingCompleted ) | |||
| 3417 | { | |||
| 3418 | if ( scrollRemaining < 0.0 ) | |||
| 3419 | { | |||
| 3420 | SDL_Rect pos = baseFrame->getSize(); | |||
| 3421 | int height = AllyStatusBarSettings_t::PlayerBars_t::entrySettings.entryHeight; | |||
| 3422 | if ( infiniteScrolling && followerDisplay.bCompact ) | |||
| 3423 | { | |||
| 3424 | height = AllyStatusBarSettings_t::PlayerBars_t::entrySettings.entryCompactHeight; | |||
| 3425 | } | |||
| 3426 | pos.y += -scrollRemaining * height; | |||
| 3427 | baseFrame->setSize(pos); | |||
| 3428 | } | |||
| 3429 | else if ( scrollRemaining >= 1.0 ) | |||
| 3430 | { | |||
| 3431 | scrollHeight += f->getSize().h; | |||
| 3432 | } | |||
| 3433 | else | |||
| 3434 | { | |||
| 3435 | scrollHeight += f->getSize().h * scrollRemaining; | |||
| 3436 | } | |||
| 3437 | scrollRemaining -= 1.0; | |||
| 3438 | } | |||
| 3439 | { | |||
| 3440 | // change frame size to allow text overflow | |||
| 3441 | SDL_Rect pos = f->getSize(); | |||
| 3442 | pos.h += 4; | |||
| 3443 | f->setSize(pos); | |||
| 3444 | } | |||
| 3445 | if ( scrollRemaining <= 0.0 ) | |||
| 3446 | { | |||
| 3447 | scrollingCompleted = true; | |||
| 3448 | } | |||
| 3449 | } | |||
| 3450 | SDL_Rect actualSize = baseFrame->getActualSize(); | |||
| 3451 | actualSize.y = scrollHeight; | |||
| 3452 | baseFrame->setActualSize(actualSize); | |||
| 3453 | } | |||
| 3454 | } | |||
| 3455 | ||||
| 3456 | void updateAllyPlayerFrame(const int player) | |||
| 3457 | { | |||
| 3458 | if ( !players[player]->hud.allyPlayerFrame ) | |||
| 3459 | { | |||
| 3460 | return; | |||
| 3461 | } | |||
| 3462 | ||||
| 3463 | auto& hud_t = players[player]->hud; | |||
| 3464 | Frame* baseFrame = hud_t.allyPlayerFrame; | |||
| 3465 | ||||
| 3466 | static ConsoleVariable<bool> cvar_playerbars("/playerbars", true); | |||
| 3467 | static ConsoleVariable<int> cvar_playerbars_debug("/playerbars_debug", -1); | |||
| 3468 | ||||
| 3469 | if ( !players[player]->isLocalPlayer() || !(*cvar_playerbars) ) | |||
| 3470 | { | |||
| 3471 | baseFrame->setDisabled(true); | |||
| 3472 | return; | |||
| 3473 | } | |||
| 3474 | ||||
| 3475 | if ( !players[player]->shootmode && !FollowerMenu[player].followerMenuIsOpen() | |||
| 3476 | && !CalloutMenu[player].calloutMenuIsOpen() | |||
| 3477 | && players[player]->gui_mode != GUI_MODE_NONE ) | |||
| 3478 | { | |||
| 3479 | baseFrame->setOpacity(0.0); | |||
| 3480 | baseFrame->setInheritParentFrameOpacity(false); | |||
| 3481 | } | |||
| 3482 | else | |||
| 3483 | { | |||
| 3484 | baseFrame->setInheritParentFrameOpacity(true); | |||
| 3485 | baseFrame->setOpacity(baseFrame->getParent()->getOpacity()); | |||
| 3486 | } | |||
| 3487 | ||||
| 3488 | baseFrame->setDisabled(false); | |||
| 3489 | SDL_Rect baseFramePos = baseFrame->getSize(); | |||
| 3490 | baseFramePos.x = 8; | |||
| 3491 | baseFramePos.y = players[player]->bUseCompactGUIWidth() ? AllyStatusBarSettings_t::PlayerBars_t::entrySettings.baseYSplitscreen : AllyStatusBarSettings_t::PlayerBars_t::entrySettings.baseY; | |||
| 3492 | baseFrame->setSize(baseFramePos); | |||
| 3493 | ||||
| 3494 | if ( *cvar_playerbars_debug >= 0 ) | |||
| 3495 | { | |||
| 3496 | if ( hud_t.playerBars.size() < *cvar_playerbars_debug ) | |||
| 3497 | { | |||
| 3498 | while ( hud_t.playerBars.size() < *cvar_playerbars_debug ) | |||
| 3499 | { | |||
| 3500 | hud_t.playerBars.push_back(std::make_pair(0, Player::HUD_t::FollowerBar_t())); | |||
| 3501 | } | |||
| 3502 | } | |||
| 3503 | else if ( hud_t.playerBars.size() > *cvar_playerbars_debug ) | |||
| 3504 | { | |||
| 3505 | hud_t.playerBars.clear(); | |||
| 3506 | } | |||
| 3507 | } | |||
| 3508 | /*if ( enableDebugKeys && keystatus[SDLK_H] ) | |||
| 3509 | { | |||
| 3510 | keystatus[SDLK_H] = 0; | |||
| 3511 | hud_t.playerBars.push_back(std::make_pair(0, Player::HUD_t::FollowerBar_t())); | |||
| 3512 | } | |||
| 3513 | ||||
| 3514 | if ( enableDebugKeys && keystatus[SDLK_J] ) | |||
| 3515 | { | |||
| 3516 | keystatus[SDLK_J] = 0; | |||
| 3517 | if ( hud_t.playerBars.size() > 0 ) | |||
| 3518 | { | |||
| 3519 | auto it = hud_t.playerBars.begin() + local_rng.rand() % hud_t.playerBars.size(); | |||
| 3520 | it->second.expired = true; | |||
| 3521 | } | |||
| 3522 | }*/ | |||
| 3523 | ||||
| 3524 | for ( int i = 0; i < MAXPLAYERS4; ++i ) | |||
| 3525 | { | |||
| 3526 | if ( i == player ) | |||
| 3527 | { | |||
| 3528 | continue; | |||
| 3529 | } | |||
| 3530 | if ( !client_disconnected[i] && players[i]->entity && !splitscreen ) | |||
| 3531 | { | |||
| 3532 | auto it = std::find_if(hud_t.playerBars.begin(), hud_t.playerBars.end(), | |||
| 3533 | [&i](const std::pair<Uint32, Player::HUD_t::FollowerBar_t>& bar) | |||
| 3534 | { | |||
| 3535 | return bar.first == i && !bar.second.expired; | |||
| 3536 | }); | |||
| 3537 | if ( it == hud_t.playerBars.end() ) | |||
| 3538 | { | |||
| 3539 | hud_t.playerBars.push_back(std::make_pair(i, Player::HUD_t::FollowerBar_t())); | |||
| 3540 | auto& bar = hud_t.playerBars.at(hud_t.playerBars.size() - 1); | |||
| 3541 | bar.second.animFadeScroll = 1.0; | |||
| 3542 | bar.second.animFadeScrollDummy = 1.0; | |||
| 3543 | } | |||
| 3544 | } | |||
| 3545 | } | |||
| 3546 | ||||
| 3547 | int activeBars = 0; | |||
| 3548 | for ( auto it = hud_t.playerBars.begin(); it != hud_t.playerBars.end(); ) | |||
| 3549 | { | |||
| 3550 | int playernum = it->first; | |||
| 3551 | if ( playernum >= 0 && playernum < MAXPLAYERS4 | |||
| 3552 | && client_disconnected[playernum] ) | |||
| 3553 | { | |||
| 3554 | it = hud_t.playerBars.erase(it); | |||
| 3555 | } | |||
| 3556 | else if ( it->second.expired && it->second.animy >= 0.999 ) | |||
| 3557 | { | |||
| 3558 | it = hud_t.playerBars.erase(it); | |||
| 3559 | } | |||
| 3560 | else | |||
| 3561 | { | |||
| 3562 | ++activeBars; | |||
| 3563 | ++it; | |||
| 3564 | } | |||
| 3565 | } | |||
| 3566 | ||||
| 3567 | updateAllyBarFrame(player, baseFrame, activeBars, activeBars, true); | |||
| 3568 | } | |||
| 3569 | ||||
| 3570 | void createEnemyBar(const int player, Frame*& frame) | |||
| 3571 | { | |||
| 3572 | auto& hud_t = players[player]->hud; | |||
| 3573 | frame = hud_t.hudFrame->addFrame("enemy bar"); | |||
| 3574 | frame->setHollow(true); | |||
| 3575 | frame->setInheritParentFrameOpacity(false); | |||
| 3576 | frame->setOpacity(0.0); | |||
| 3577 | const int barTotalHeight = hud_t.ENEMYBAR_FRAME_HEIGHT; | |||
| 3578 | const int barStartY = (hud_t.hudFrame->getSize().h - hud_t.ENEMYBAR_FRAME_START_Y - 100); | |||
| 3579 | const int barWidth = hud_t.ENEMYBAR_FRAME_WIDTH; | |||
| 3580 | ||||
| 3581 | SDL_Rect pos{ (hud_t.hudFrame->getSize().w / 2) - barWidth / 2 - 6, barStartY, barWidth, barTotalHeight }; | |||
| 3582 | frame->setSize(pos); | |||
| 3583 | ||||
| 3584 | auto bg = frame->addImage(pos, 0xFFFFFFFF, "*#images/ui/HUD/enemybar/HUD_EnemyHP_Back_Body_01.png", "base img"); | |||
| 3585 | bg->pos.x = 6; | |||
| 3586 | bg->pos.h = 34; | |||
| 3587 | bg->pos.y = 4; | |||
| 3588 | bg->pos.w = 548; | |||
| 3589 | bg->color = makeColor(255, 255, 255, 255); | |||
| 3590 | ||||
| 3591 | auto bgEndCap = frame->addImage(pos, 0xFFFFFFFF, "*#images/ui/HUD/enemybar/HUD_EnemyHP_Back_Cap_01.png", "base img endcap"); | |||
| 3592 | bgEndCap->pos.x = bg->pos.x + bg->pos.w; | |||
| 3593 | bgEndCap->pos.h = bg->pos.h; | |||
| 3594 | bgEndCap->pos.y = bg->pos.y; | |||
| 3595 | bgEndCap->pos.w = 8; | |||
| 3596 | bgEndCap->color = bg->color; | |||
| 3597 | ||||
| 3598 | auto dmgFrame = frame->addFrame("bar dmg frame"); | |||
| 3599 | dmgFrame->setSize(SDL_Rect{ bg->pos.x, bg->pos.y, bg->pos.w + bgEndCap->pos.w, 34 }); | |||
| 3600 | dmgFrame->setInheritParentFrameOpacity(false); | |||
| 3601 | auto dmg = dmgFrame->addImage(pos, 0xFFFFFFFF, "*#images/ui/HUD/enemybar/HUD_EnemyHP_DMG_Body_01.png", "dmg img"); | |||
| 3602 | dmg->pos.x = 0; | |||
| 3603 | dmg->pos.h = bg->pos.h; | |||
| 3604 | dmg->pos.y = 0; | |||
| 3605 | dmg->pos.w = 548 / 2 + 100; | |||
| 3606 | dmg->color = makeColor(255, 255, 255, 255); | |||
| 3607 | ||||
| 3608 | auto dmgEndCap = dmgFrame->addImage(pos, 0xFFFFFFFF, "*#images/ui/HUD/enemybar/HUD_EnemyHP_DMG_Cap_01.png", "dmg img endcap"); | |||
| 3609 | dmgEndCap->pos.x = dmg->pos.w; | |||
| 3610 | dmgEndCap->pos.h = dmg->pos.h; | |||
| 3611 | dmgEndCap->pos.y = 0; | |||
| 3612 | dmgEndCap->pos.w = 10; | |||
| 3613 | dmgEndCap->color = dmg->color; | |||
| 3614 | ||||
| 3615 | /*auto bubbles = dmgFrame->addImage(pos, 0xFFFFFFFF, "*#images/ui/HUD/enemybar/HUD_EnemyHP_Bubbles_00.png", "img bubbles"); | |||
| 3616 | bubbles->pos.x = 0; | |||
| 3617 | bubbles->pos.h = 20; | |||
| 3618 | bubbles->pos.y = dmgFrame->getSize().h / 2 - bubbles->pos.h / 2; | |||
| 3619 | if ( auto img = Image::get(bubbles->path.c_str()) ) | |||
| 3620 | { | |||
| 3621 | bubbles->pos.w = img->getWidth(); | |||
| 3622 | }*/ | |||
| 3623 | ||||
| 3624 | auto progressFrame = frame->addFrame("bar progress frame"); | |||
| 3625 | progressFrame->setSize(SDL_Rect{ bg->pos.x, bg->pos.y + 2, bg->pos.w + bgEndCap->pos.w, 30 }); | |||
| 3626 | progressFrame->setOpacity(100.0); | |||
| 3627 | auto fg = progressFrame->addImage(pos, 0xFFFFFFFF, "*#images/ui/HUD/enemybar/HUD_EnemyHP_Fill_Body_00.png", "progress img"); | |||
| 3628 | fg->pos.x = 0; | |||
| 3629 | fg->pos.h = bg->pos.h - 4; | |||
| 3630 | fg->pos.y = 0; | |||
| 3631 | fg->pos.w = 548; | |||
| 3632 | ||||
| 3633 | auto fgEndCap = progressFrame->addImage(pos, 0xFFFFFFFF, "*#images/ui/HUD/enemybar/HUD_EnemyHP_Fill_Cap_00.png", "progress img endcap"); | |||
| 3634 | fgEndCap->pos.x = fg->pos.x + fg->pos.w; | |||
| 3635 | fgEndCap->pos.h = fg->pos.h; | |||
| 3636 | fgEndCap->pos.y = 0; | |||
| 3637 | if ( auto img = Image::get(fgEndCap->path.c_str()) ) | |||
| 3638 | { | |||
| 3639 | fgEndCap->pos.w = img->getWidth(); | |||
| 3640 | } | |||
| 3641 | ||||
| 3642 | auto skullFrame = frame->addFrame("skull frame"); | |||
| 3643 | skullFrame->setSize(SDL_Rect{ 0, 0, 24, 44 }); | |||
| 3644 | auto skull = skullFrame->addImage(skullFrame->getSize(), 0xFFFFFFFF, "*#images/ui/HUD/enemybar/HUD_EnemyHP_Face4_00.png", "skull 0 img"); | |||
| 3645 | skull = skullFrame->addImage(skullFrame->getSize(), 0xFFFFFFFF, "*#images/ui/HUD/enemybar/HUD_EnemyHP_Face3_00.png", "skull 25 img"); | |||
| 3646 | skull = skullFrame->addImage(skullFrame->getSize(), 0xFFFFFFFF, "*#images/ui/HUD/enemybar/HUD_EnemyHP_Face2_00.png", "skull 50 img"); | |||
| 3647 | skull = skullFrame->addImage(skullFrame->getSize(), 0xFFFFFFFF, "*#images/ui/HUD/enemybar/HUD_EnemyHP_Face1_00.png", "skull 100 img"); | |||
| 3648 | ||||
| 3649 | std::string font = "fonts/pixel_maz.ttf#32#2"; | |||
| 3650 | Uint32 color = makeColor(235, 191, 140, 255); | |||
| 3651 | auto enemyName = frame->addField("enemy name txt", 128); | |||
| 3652 | enemyName->setSize(SDL_Rect{ 0, 0, frame->getSize().w, frame->getSize().h}); | |||
| 3653 | enemyName->setFont(font.c_str()); | |||
| 3654 | enemyName->setColor(color); | |||
| 3655 | enemyName->setHJustify(Field::justify_t::CENTER); | |||
| 3656 | enemyName->setVJustify(Field::justify_t::CENTER); | |||
| 3657 | enemyName->setText(""); | |||
| 3658 | enemyName->setOntop(true); | |||
| 3659 | ||||
| 3660 | auto dmgText = hud_t.hudFrame->addField("enemy dmg txt", 128); | |||
| 3661 | dmgText->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 3662 | dmgText->setFont("fonts/pixel_maz.ttf#32#2"); | |||
| 3663 | dmgText->setColor(color); | |||
| 3664 | dmgText->setHJustify(Field::justify_t::LEFT); | |||
| 3665 | dmgText->setVJustify(Field::justify_t::TOP); | |||
| 3666 | dmgText->setText("0"); | |||
| 3667 | dmgText->setOntop(true); | |||
| 3668 | } | |||
| 3669 | ||||
| 3670 | std::vector<std::vector<std::string>> playerXPCapPaths = { | |||
| 3671 | { | |||
| 3672 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_00.png", | |||
| 3673 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_00a.png", | |||
| 3674 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_00b.png", | |||
| 3675 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_00c.png", | |||
| 3676 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_00d.png", | |||
| 3677 | }, | |||
| 3678 | { | |||
| 3679 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_01.png", | |||
| 3680 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_01a.png", | |||
| 3681 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_01b.png", | |||
| 3682 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_01c.png", | |||
| 3683 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_01d.png", | |||
| 3684 | }, | |||
| 3685 | { | |||
| 3686 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_02.png", | |||
| 3687 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_02a.png", | |||
| 3688 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_02b.png", | |||
| 3689 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_02c.png", | |||
| 3690 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_02d.png", | |||
| 3691 | }, | |||
| 3692 | { | |||
| 3693 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_03.png", | |||
| 3694 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_03a.png", | |||
| 3695 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_03b.png", | |||
| 3696 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_03c.png", | |||
| 3697 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_03d.png", | |||
| 3698 | }, | |||
| 3699 | { | |||
| 3700 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_04.png", | |||
| 3701 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_04a.png", | |||
| 3702 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_04b.png", | |||
| 3703 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_04c.png", | |||
| 3704 | "*#images/ui/HUD/xpbar/HUD_Exp_SandCap_04d.png", | |||
| 3705 | } | |||
| 3706 | }; | |||
| 3707 | ||||
| 3708 | void createXPBar(const int player) | |||
| 3709 | { | |||
| 3710 | auto& hud_t = players[player]->hud; | |||
| 3711 | hud_t.xpFrame = hud_t.hudFrame->addFrame("xp bar"); | |||
| 3712 | hud_t.xpFrame->setHollow(true); | |||
| 3713 | ||||
| 3714 | const int xpBarStartY = (hud_t.hudFrame->getSize().h) - hud_t.XP_FRAME_START_Y; | |||
| 3715 | const int xpBarWidth = hud_t.XP_FRAME_WIDTH; | |||
| 3716 | const int xpBarTotalHeight = hud_t.XP_FRAME_HEIGHT; | |||
| 3717 | SDL_Rect pos { (hud_t.hudFrame->getSize().w / 2) - xpBarWidth / 2, xpBarStartY, xpBarWidth, xpBarTotalHeight }; | |||
| 3718 | hud_t.xpFrame->setSize(pos); | |||
| 3719 | ||||
| 3720 | //auto bg = hud_t.xpFrame->addImage(pos, 0xFFFFFFFF, "*#images/ui/HUD/xpbar/HUD_Bars_Base_00.png", "xp img base"); | |||
| 3721 | auto bg = hud_t.xpFrame->addImage(pos, 0xFFFFFFFF, "*#images/ui/HUD/xpbar/HUD_Exp_Surround_01.png", "xp img base"); | |||
| 3722 | bg->pos.x = 0; | |||
| 3723 | bg->pos.h = 26; | |||
| 3724 | bg->pos.y = 4; | |||
| 3725 | auto bgFlair = hud_t.xpFrame->addImage(SDL_Rect{4, 10, 0, 14}, makeColor(255, 255, 255, 192), "*#images/ui/HUD/xpbar/HUD_Exp_GlassShine_03.png", "xp img base flair"); | |||
| 3726 | ||||
| 3727 | // xpProgress only adjusts width | |||
| 3728 | const int progressBarHeight = 22; | |||
| 3729 | /*auto xpProgress = hud_t.xpFrame->addImage(SDL_Rect{ 0, 6, 1, progressBarHeight }, 0xFFFFFFFF, | |||
| 3730 | "*#images/ui/HUD/xpbar/HUD_Bars_ExpMid_00.png", "xp img progress");*/ | |||
| 3731 | auto progressClipFrame = hud_t.xpFrame->addFrame("xp progress clipping frame"); | |||
| 3732 | progressClipFrame->setSize(SDL_Rect{ 0, 6, 1, progressBarHeight }); | |||
| 3733 | ||||
| 3734 | std::string bodyPath = "*#images/ui/HUD/xpbar/HUD_Exp_SandBody2_"; | |||
| 3735 | int xpPathNum = player; | |||
| 3736 | if ( !colorblind_lobby ) | |||
| 3737 | { | |||
| 3738 | switch ( player ) | |||
| 3739 | { | |||
| 3740 | case 0: | |||
| 3741 | default: | |||
| 3742 | bodyPath += "00.png"; | |||
| 3743 | break; | |||
| 3744 | case 1: | |||
| 3745 | bodyPath += "01.png"; | |||
| 3746 | break; | |||
| 3747 | case 2: | |||
| 3748 | bodyPath += "02.png"; | |||
| 3749 | break; | |||
| 3750 | case 3: | |||
| 3751 | bodyPath += "03.png"; | |||
| 3752 | break; | |||
| 3753 | } | |||
| 3754 | } | |||
| 3755 | else | |||
| 3756 | { | |||
| 3757 | switch ( player ) | |||
| 3758 | { | |||
| 3759 | case 0: | |||
| 3760 | default: | |||
| 3761 | bodyPath += "02.png"; | |||
| 3762 | xpPathNum = 2; | |||
| 3763 | break; | |||
| 3764 | case 1: | |||
| 3765 | bodyPath += "03.png"; | |||
| 3766 | xpPathNum = 3; | |||
| 3767 | break; | |||
| 3768 | case 2: | |||
| 3769 | bodyPath += "01.png"; | |||
| 3770 | xpPathNum = 1; | |||
| 3771 | break; | |||
| 3772 | case 3: | |||
| 3773 | bodyPath += "04.png"; | |||
| 3774 | xpPathNum = 4; | |||
| 3775 | break; | |||
| 3776 | } | |||
| 3777 | } | |||
| 3778 | if ( player >= playerXPCapPaths.size() ) | |||
| 3779 | { | |||
| 3780 | xpPathNum = 0; | |||
| 3781 | } | |||
| 3782 | ||||
| 3783 | auto progressClipImg = progressClipFrame->addImage(SDL_Rect{ 0, 0, 634, progressBarHeight }, 0xFFFFFFFF, | |||
| 3784 | bodyPath.c_str(), "xp img progress clipped"); | |||
| 3785 | ||||
| 3786 | auto xpProgress = hud_t.xpFrame->addImage(SDL_Rect{ 0, 6, 1, progressBarHeight }, 0xFFFFFFFF, | |||
| 3787 | bodyPath.c_str(), "xp img progress"); | |||
| 3788 | ||||
| 3789 | // xpProgressEndCap only adjusts x position based on xpProgress->pos.x + xpProgress->pos.w | |||
| 3790 | /*auto xpProgressEndCap = hud_t.xpFrame->addImage(SDL_Rect{0, 6, 8, progressBarHeight }, 0xFFFFFFFF, | |||
| 3791 | "*#images/ui/HUD/xpbar/HUD_Bars_ExpEnd_00.png", "xp img progress endcap");*/ | |||
| 3792 | ||||
| 3793 | auto xpProgressEndCap = hud_t.xpFrame->addImage(SDL_Rect{ 0, 6, 38, progressBarHeight }, 0xFFFFFFFF, | |||
| 3794 | playerXPCapPaths[xpPathNum][0].c_str(), "xp img progress endcap"); | |||
| 3795 | ||||
| 3796 | ||||
| 3797 | const int endCapWidth = 26; | |||
| 3798 | SDL_Rect endCapPos {0, 0, endCapWidth, xpBarTotalHeight}; | |||
| 3799 | auto endCapLeft = hud_t.xpFrame->addImage(endCapPos, 0xFFFFFFFF, "*#images/ui/HUD/xpbar/HUD_Bars_ExpCap1_00.png", "xp img endcap left"); | |||
| 3800 | endCapLeft->ontop = true; | |||
| 3801 | endCapPos.x = pos.w - endCapPos.w; | |||
| 3802 | auto endCapRight = hud_t.xpFrame->addImage(endCapPos, 0xFFFFFFFF, "*#images/ui/HUD/xpbar/HUD_Bars_ExpCap2_00.png", "xp img endcap right"); | |||
| 3803 | endCapRight->ontop = true; | |||
| 3804 | ||||
| 3805 | const int textWidth = 72; | |||
| 3806 | auto font = "fonts/pixel_maz.ttf#32#2"; | |||
| 3807 | auto textStatic = hud_t.xpFrame->addField("xp text static", 16); | |||
| 3808 | textStatic->setText(Language::get(6106)); | |||
| 3809 | textStatic->setOntop(true); | |||
| 3810 | textStatic->setSize(SDL_Rect{ pos.w / 2 - 4, 0, textWidth, pos.h }); // x - 4 to center the slash | |||
| 3811 | textStatic->setFont(font); | |||
| 3812 | textStatic->setVJustify(Field::justify_t::CENTER); | |||
| 3813 | textStatic->setHJustify(Field::justify_t::LEFT); | |||
| 3814 | textStatic->setColor(makeColor( 255, 255, 255, 255)); | |||
| 3815 | ||||
| 3816 | auto text = hud_t.xpFrame->addField("xp text current", 16); | |||
| 3817 | text->setText("0"); | |||
| 3818 | text->setOntop(true); | |||
| 3819 | text->setSize(SDL_Rect{ pos.w / 2 - (4 * 2) - textWidth, 0, textWidth, pos.h }); // x - 4 to center the slash | |||
| 3820 | text->setFont(font); | |||
| 3821 | text->setVJustify(Field::justify_t::CENTER); | |||
| 3822 | text->setHJustify(Field::justify_t::RIGHT); | |||
| 3823 | text->setColor(makeColor( 255, 255, 255, 255)); | |||
| 3824 | ||||
| 3825 | auto textLevel = hud_t.xpFrame->addField("xp text lvl", 64); | |||
| 3826 | textLevel->setText(""); | |||
| 3827 | textLevel->setOntop(true); | |||
| 3828 | textLevel->setDisabled(true); | |||
| 3829 | textLevel->setSize(SDL_Rect{ 0, 0, 0, pos.h }); // x - 4 to center the slash | |||
| 3830 | textLevel->setFont(font); | |||
| 3831 | textLevel->setVJustify(Field::justify_t::CENTER); | |||
| 3832 | textLevel->setHJustify(Field::justify_t::LEFT); | |||
| 3833 | textLevel->setColor(makeColor(255, 255, 255, 255)); | |||
| 3834 | ||||
| 3835 | auto textClass = hud_t.xpFrame->addField("xp text class", 64); | |||
| 3836 | textClass->setText(""); | |||
| 3837 | textClass->setOntop(true); | |||
| 3838 | textClass->setDisabled(true); | |||
| 3839 | textClass->setSize(SDL_Rect{ 0, 0, 0, pos.h }); // x - 4 to center the slash | |||
| 3840 | textClass->setFont(font); | |||
| 3841 | textClass->setVJustify(Field::justify_t::CENTER); | |||
| 3842 | textClass->setHJustify(Field::justify_t::LEFT); | |||
| 3843 | textClass->setColor(makeColor(255, 255, 255, 255)); | |||
| 3844 | } | |||
| 3845 | ||||
| 3846 | void createHotbar(const int player) | |||
| 3847 | { | |||
| 3848 | auto& hotbar_t = players[player]->hotbar; | |||
| 3849 | if ( !hotbar_t.hotbarFrame ) | |||
| 3850 | { | |||
| 3851 | return; | |||
| 3852 | } | |||
| 3853 | Uint32 color = makeColor( 255, 255, 255, hotbarSlotOpacity); | |||
| 3854 | SDL_Rect slotPos{ 0, 0, hotbar_t.getSlotSize(), hotbar_t.getSlotSize() }; | |||
| 3855 | std::array<int, NUM_HOTBAR_SLOTS> slotCreationOrder = { | |||
| 3856 | 0, 2, 3, 5, 6, 8, 9, 1, 4, 7 | |||
| 3857 | }; | |||
| 3858 | for ( auto& i : slotCreationOrder ) | |||
| 3859 | { | |||
| 3860 | char slotname[32]; | |||
| 3861 | snprintf(slotname, sizeof(slotname), "hotbar slot %d", i); | |||
| 3862 | auto slot = hotbar_t.hotbarFrame->addFrame(slotname); | |||
| 3863 | slot->setSize(slotPos); | |||
| 3864 | slot->addImage(slotPos, color, "*#images/ui/HUD/hotbar/HUD_Quickbar_Slot_Box_02.png", "slot img"); | |||
| 3865 | hotbar_t.hotbarSlotFrames[i] = slot; | |||
| 3866 | ||||
| 3867 | char glyphname[32]; | |||
| 3868 | snprintf(glyphname, sizeof(glyphname), "hotbar glyph %d", i); | |||
| 3869 | auto path = Input::getGlyphPathForInput("ButtonA", false, Input::getControllerType(player)); | |||
| 3870 | auto glyph = hotbar_t.hotbarFrame->addImage(slotPos, 0xFFFFFFFF, path.c_str(), glyphname); | |||
| 3871 | glyph->disabled = true; | |||
| 3872 | } | |||
| 3873 | ||||
| 3874 | auto font = "fonts/pixel_maz.ttf#32#2"; | |||
| 3875 | ||||
| 3876 | for ( int i = 0; i < NUM_HOTBAR_SLOTS; ++i ) | |||
| 3877 | { | |||
| 3878 | auto slot = hotbar_t.getHotbarSlotFrame(i); | |||
| 3879 | assert(slot)(static_cast<void> (0)); | |||
| 3880 | ||||
| 3881 | auto itemSlot = slot->addFrame("hotbar slot item"); | |||
| 3882 | SDL_Rect itemSlotTempSize = slot->getSize(); | |||
| 3883 | itemSlotTempSize.w -= 4; | |||
| 3884 | itemSlotTempSize.h -= 4; | |||
| 3885 | itemSlot->setSize(itemSlotTempSize); // slightly shrink to align inner item elements within rect. | |||
| 3886 | createPlayerInventorySlotFrameElements(itemSlot); | |||
| 3887 | itemSlot->setSize(slot->getSize()); | |||
| 3888 | ||||
| 3889 | char numStr[32]; | |||
| 3890 | if ( i + 1 == 10 ) | |||
| 3891 | { | |||
| 3892 | snprintf(numStr, sizeof(numStr), "%d", 0); | |||
| 3893 | } | |||
| 3894 | else | |||
| 3895 | { | |||
| 3896 | snprintf(numStr, sizeof(numStr), "%d", i + 1); | |||
| 3897 | } | |||
| 3898 | auto text = slot->addField("slot num text", 32); | |||
| 3899 | text->setText(numStr); | |||
| 3900 | text->setSize(SDL_Rect{ 0, -4, slotPos.w, slotPos.h }); | |||
| 3901 | text->setFont(font); | |||
| 3902 | text->setVJustify(Field::justify_t::TOP); | |||
| 3903 | text->setHJustify(Field::justify_t::LEFT); | |||
| 3904 | text->setOntop(true); | |||
| 3905 | } | |||
| 3906 | ||||
| 3907 | auto highlightFrame = hotbar_t.hotbarFrame->addFrame("hotbar highlight"); | |||
| 3908 | highlightFrame->setSize(slotPos); | |||
| 3909 | highlightFrame->addImage(slotPos, color, "*#images/ui/HUD/hotbar/HUD_Quickbar_Slot_HighlightBox_02.png", "highlight img"); | |||
| 3910 | ||||
| 3911 | auto itemSlot = highlightFrame->addFrame("hotbar slot item"); | |||
| 3912 | SDL_Rect itemSlotTempSize = slotPos; | |||
| 3913 | itemSlotTempSize.w -= 4; | |||
| 3914 | itemSlotTempSize.h -= 4; | |||
| 3915 | itemSlot->setSize(itemSlotTempSize); | |||
| 3916 | createPlayerInventorySlotFrameElements(itemSlot); // slightly shrink to align inner item elements within rect. | |||
| 3917 | itemSlot->setSize(highlightFrame->getSize()); | |||
| 3918 | ||||
| 3919 | { | |||
| 3920 | auto oldSelectedFrame = hotbar_t.hotbarFrame->addFrame("hotbar old selected item"); | |||
| 3921 | SDL_Rect oldSelectedFramePos = slotPos; | |||
| 3922 | oldSelectedFramePos.w -= 2; | |||
| 3923 | oldSelectedFramePos.h -= 2; | |||
| 3924 | oldSelectedFrame->setSize(oldSelectedFramePos); | |||
| 3925 | oldSelectedFrame->setDisabled(true); | |||
| 3926 | ||||
| 3927 | const int itemSpriteSize = players[oldSelectedFrame->getOwner()]->inventoryUI.getItemSpriteSize(); | |||
| 3928 | SDL_Rect itemSpriteBorder{ 5, 5, itemSpriteSize, itemSpriteSize }; | |||
| 3929 | ||||
| 3930 | color = makeColor( 0, 255, 255, 255); | |||
| 3931 | auto oldImg = oldSelectedFrame->addImage(itemSpriteBorder, | |||
| 3932 | makeColor( 255, 255, 255, 128), "", "hotbar old selected item"); | |||
| 3933 | oldImg->disabled = true; | |||
| 3934 | oldSelectedFrame->addImage(SDL_Rect{ 0, 0, oldSelectedFrame->getSize().w, oldSelectedFrame->getSize().h }, | |||
| 3935 | color, "*images/system/hotbar_slot.png", "hotbar old selected highlight"); | |||
| 3936 | ||||
| 3937 | auto oldCursorFrame = hotbar_t.hotbarFrame->addFrame("hotbar old item cursor"); | |||
| 3938 | oldCursorFrame->setSize(SDL_Rect{ 0, 0, oldSelectedFramePos.w + 16, oldSelectedFramePos.h + 16 }); | |||
| 3939 | oldCursorFrame->setDisabled(true); | |||
| 3940 | color = makeColor( 255, 255, 255, oldSelectedCursorOpacity); | |||
| 3941 | oldCursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 3942 | color, "*#images/ui/Inventory/SelectorGrey_TL.png", "hotbar old cursor topleft"); | |||
| 3943 | oldCursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 3944 | color, "*#images/ui/Inventory/SelectorGrey_TR.png", "hotbar old cursor topright"); | |||
| 3945 | oldCursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 3946 | color, "*#images/ui/Inventory/SelectorGrey_BL.png", "hotbar old cursor bottomleft"); | |||
| 3947 | oldCursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 3948 | color, "*#images/ui/Inventory/SelectorGrey_BR.png", "hotbar old cursor bottomright"); | |||
| 3949 | ||||
| 3950 | auto cursorFrame = hotbar_t.hotbarFrame->addFrame("shootmode selected item cursor"); | |||
| 3951 | cursorFrame->setSize(SDL_Rect{ 0, 0, oldSelectedFramePos.w + 16, oldSelectedFramePos.h + 16 }); | |||
| 3952 | cursorFrame->setDisabled(true); | |||
| 3953 | color = makeColor( 255, 255, 255, selectedCursorOpacity); | |||
| 3954 | cursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 3955 | color, "*#images/ui/Inventory/Selector_TL.png", "shootmode selected cursor topleft"); | |||
| 3956 | cursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 3957 | color, "*#images/ui/Inventory/Selector_TR.png", "shootmode selected cursor topright"); | |||
| 3958 | cursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 3959 | color, "*#images/ui/Inventory/Selector_BL.png", "shootmode selected cursor bottomleft"); | |||
| 3960 | cursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 3961 | color, "*#images/ui/Inventory/Selector_BR.png", "shootmode selected cursor bottomright"); | |||
| 3962 | } | |||
| 3963 | ||||
| 3964 | auto cancelPromptTxt = hotbar_t.hotbarFrame->addField("hotbar cancel prompt", 32); | |||
| 3965 | cancelPromptTxt->setText(Language::get(3063)); | |||
| 3966 | cancelPromptTxt->setSize(SDL_Rect{ 0, 0, 100, 24 }); | |||
| 3967 | cancelPromptTxt->setDisabled(true); | |||
| 3968 | cancelPromptTxt->setFont(font); | |||
| 3969 | cancelPromptTxt->setVJustify(Field::justify_t::TOP); | |||
| 3970 | cancelPromptTxt->setHJustify(Field::justify_t::LEFT); | |||
| 3971 | auto cancelPromptGlyph = hotbar_t.hotbarFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 3972 | 0xFFFFFFFF, "", "hotbar cancel glyph"); | |||
| 3973 | cancelPromptGlyph->disabled = true; | |||
| 3974 | ||||
| 3975 | auto text = highlightFrame->addField("slot num text", 32); | |||
| 3976 | text->setText(""); | |||
| 3977 | text->setSize(SDL_Rect{ 0, -4, slotPos.w, slotPos.h }); | |||
| 3978 | text->setFont(font); | |||
| 3979 | text->setVJustify(Field::justify_t::TOP); | |||
| 3980 | text->setHJustify(Field::justify_t::LEFT); | |||
| 3981 | text->setOntop(true); | |||
| 3982 | } | |||
| 3983 | ||||
| 3984 | void createUINavigation(const int player) | |||
| 3985 | { | |||
| 3986 | auto& hud_t = players[player]->hud; | |||
| 3987 | auto& uiNavFrame = hud_t.uiNavFrame; | |||
| 3988 | uiNavFrame = hud_t.hudFrame->addFrame("ui navigation"); | |||
| 3989 | uiNavFrame->setHollow(true); | |||
| 3990 | uiNavFrame->setBorder(0); | |||
| 3991 | uiNavFrame->setOwner(player); | |||
| 3992 | uiNavFrame->setSize(SDL_Rect{ 0, 0, hud_t.hudFrame->getSize().w, hud_t.hudFrame->getSize().h }); | |||
| 3993 | uiNavFrame->setDisabled(true); | |||
| 3994 | { | |||
| 3995 | const int glyphSize = 32; | |||
| 3996 | const char* buttonFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 3997 | auto magicButton = uiNavFrame->addButton("magic button"); | |||
| 3998 | magicButton->setText(Language::get(4115)); | |||
| 3999 | magicButton->setFont(buttonFont); | |||
| 4000 | magicButton->setBackground("*#images/ui/HUD/HUD_Button_Base_Small_00.png"); | |||
| 4001 | magicButton->setBackgroundActivated("*#images/ui/HUD/HUD_Button_Base_SmallPress_00.png"); | |||
| 4002 | magicButton->setBackgroundHighlighted("*#images/ui/HUD/HUD_Button_Base_SmallHigh_00.png"); | |||
| 4003 | magicButton->setSize(SDL_Rect{ 0, 0, 98, 38 }); | |||
| 4004 | magicButton->setHideGlyphs(true); | |||
| 4005 | magicButton->setHideKeyboardGlyphs(true); | |||
| 4006 | magicButton->setHideSelectors(true); | |||
| 4007 | magicButton->setMenuConfirmControlType(0); | |||
| 4008 | magicButton->setColor(makeColor(255, 255, 255, 255)); | |||
| 4009 | magicButton->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 4010 | magicButton->setCallback([](Button& button) { | |||
| 4011 | if ( inputs.getVirtualMouse(button.getOwner())->draw_cursor ) | |||
| 4012 | { | |||
| 4013 | // prevent 1 frame flickering of hud.cursor after click | |||
| 4014 | players[button.getOwner()]->GUI.setHoveringOverModuleButton(Player::GUI_t::MODULE_INVENTORY); | |||
| 4015 | } | |||
| 4016 | if ( players[button.getOwner()]->inventory_mode == INVENTORY_MODE_ITEM ) | |||
| 4017 | { | |||
| 4018 | players[button.getOwner()]->GUI.activateModule(Player::GUI_t::MODULE_INVENTORY); | |||
| 4019 | players[button.getOwner()]->gui_mode = GUI_MODE_INVENTORY; | |||
| 4020 | players[button.getOwner()]->inventoryUI.cycleInventoryTab(); | |||
| 4021 | players[button.getOwner()]->inventoryUI.spellPanel.openSpellPanel(); | |||
| 4022 | } | |||
| 4023 | else if ( players[button.getOwner()]->inventory_mode == INVENTORY_MODE_SPELL ) | |||
| 4024 | { | |||
| 4025 | players[button.getOwner()]->GUI.activateModule(Player::GUI_t::MODULE_SPELLS); | |||
| 4026 | players[button.getOwner()]->gui_mode = GUI_MODE_INVENTORY; | |||
| 4027 | players[button.getOwner()]->inventoryUI.cycleInventoryTab(); | |||
| 4028 | players[button.getOwner()]->inventoryUI.spellPanel.closeSpellPanel(); | |||
| 4029 | } | |||
| 4030 | }); | |||
| 4031 | auto magicButtonGlyph = uiNavFrame->addImage(SDL_Rect{ 0, 0, glyphSize, glyphSize }, | |||
| 4032 | 0xFFFFFFFF, "images/system/white.png", "magic button glyph")->disabled = true; | |||
| 4033 | ||||
| 4034 | auto statusButton = uiNavFrame->addButton("status button"); | |||
| 4035 | statusButton->setText(Language::get(4118)); | |||
| 4036 | statusButton->setFont(buttonFont); | |||
| 4037 | statusButton->setBackground("*#images/ui/HUD/HUD_Button_Base_Small_00.png"); | |||
| 4038 | statusButton->setBackgroundActivated("*#images/ui/HUD/HUD_Button_Base_SmallPress_00.png"); | |||
| 4039 | statusButton->setBackgroundHighlighted("*#images/ui/HUD/HUD_Button_Base_SmallHigh_00.png"); | |||
| 4040 | statusButton->setSize(SDL_Rect{ 0, 0, 98, 38 }); | |||
| 4041 | statusButton->setHideGlyphs(true); | |||
| 4042 | statusButton->setHideKeyboardGlyphs(true); | |||
| 4043 | statusButton->setHideSelectors(true); | |||
| 4044 | statusButton->setMenuConfirmControlType(0); | |||
| 4045 | statusButton->setColor(makeColor(255, 255, 255, 255)); | |||
| 4046 | statusButton->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 4047 | statusButton->setCallback([](Button& button) { | |||
| 4048 | Player::soundActivate(); | |||
| 4049 | if ( players[button.getOwner()]->hud.compactLayoutMode != Player::HUD_t::COMPACT_LAYOUT_CHARSHEET ) | |||
| 4050 | { | |||
| 4051 | players[button.getOwner()]->inventoryUI.slideOutPercent = 1.0; | |||
| 4052 | } | |||
| 4053 | players[button.getOwner()]->hud.compactLayoutMode = Player::HUD_t::COMPACT_LAYOUT_CHARSHEET; | |||
| 4054 | if ( inputs.getVirtualMouse(button.getOwner())->draw_cursor ) | |||
| 4055 | { | |||
| 4056 | // prevent 1 frame flickering of hud.cursor after click | |||
| 4057 | players[button.getOwner()]->GUI.setHoveringOverModuleButton(Player::GUI_t::MODULE_INVENTORY); | |||
| 4058 | } | |||
| 4059 | players[button.getOwner()]->GUI.activateModule(Player::GUI_t::MODULE_CHARACTERSHEET); | |||
| 4060 | if ( players[button.getOwner()]->characterSheet.selectedElement == Player::CharacterSheet_t::SHEET_UNSELECTED ) | |||
| 4061 | { | |||
| 4062 | players[button.getOwner()]->characterSheet.selectElement(Player::CharacterSheet_t::SHEET_OPEN_MAP, false, false); | |||
| 4063 | } | |||
| 4064 | players[button.getOwner()]->GUI.warpControllerToModule(false); | |||
| 4065 | }); | |||
| 4066 | auto statusButtonGlyph = uiNavFrame->addImage(SDL_Rect{ 0, 0, glyphSize, glyphSize }, | |||
| 4067 | 0xFFFFFFFF, "images/system/white.png", "status button glyph")->disabled = true; | |||
| 4068 | ||||
| 4069 | auto itemsButton = uiNavFrame->addButton("items button"); | |||
| 4070 | itemsButton->setText(Language::get(4116)); | |||
| 4071 | itemsButton->setFont(buttonFont); | |||
| 4072 | itemsButton->setBackground("*#images/ui/HUD/HUD_Button_Base_Small_00.png"); | |||
| 4073 | itemsButton->setBackgroundActivated("*#images/ui/HUD/HUD_Button_Base_SmallPress_00.png"); | |||
| 4074 | itemsButton->setBackgroundHighlighted("*#images/ui/HUD/HUD_Button_Base_SmallHigh_00.png"); | |||
| 4075 | itemsButton->setSize(SDL_Rect{ 0, 0, 98, 38 }); | |||
| 4076 | itemsButton->setHideGlyphs(true); | |||
| 4077 | itemsButton->setHideKeyboardGlyphs(true); | |||
| 4078 | itemsButton->setHideSelectors(true); | |||
| 4079 | itemsButton->setMenuConfirmControlType(0); | |||
| 4080 | itemsButton->setColor(makeColor(255, 255, 255, 255)); | |||
| 4081 | itemsButton->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 4082 | itemsButton->setCallback([](Button& button) { | |||
| 4083 | if ( players[button.getOwner()]->hud.compactLayoutMode != Player::HUD_t::COMPACT_LAYOUT_INVENTORY ) | |||
| 4084 | { | |||
| 4085 | Player::soundActivate(); | |||
| 4086 | } | |||
| 4087 | players[button.getOwner()]->hud.compactLayoutMode = Player::HUD_t::COMPACT_LAYOUT_INVENTORY; | |||
| 4088 | if ( inputs.getVirtualMouse(button.getOwner())->draw_cursor ) | |||
| 4089 | { | |||
| 4090 | // prevent 1 frame flickering of hud.cursor after click | |||
| 4091 | players[button.getOwner()]->GUI.setHoveringOverModuleButton(Player::GUI_t::MODULE_INVENTORY); | |||
| 4092 | } | |||
| 4093 | if ( players[button.getOwner()]->inventory_mode == INVENTORY_MODE_SPELL | |||
| 4094 | && players[button.getOwner()]->GUI.activeModule == Player::GUI_t::MODULE_SPELLS ) | |||
| 4095 | { | |||
| 4096 | players[button.getOwner()]->inventoryUI.cycleInventoryTab(); | |||
| 4097 | } | |||
| 4098 | else | |||
| 4099 | { | |||
| 4100 | players[button.getOwner()]->openStatusScreen(GUI_MODE_INVENTORY, INVENTORY_MODE_ITEM, Player::GUI_t::MODULE_INVENTORY); | |||
| 4101 | } | |||
| 4102 | }); | |||
| 4103 | ||||
| 4104 | auto itemsButtonGlyph = uiNavFrame->addImage(SDL_Rect{ 0, 0, glyphSize, glyphSize }, | |||
| 4105 | 0xFFFFFFFF, "images/system/white.png", "items button glyph")->disabled = true; | |||
| 4106 | ||||
| 4107 | auto skillsButton = uiNavFrame->addButton("skills button"); | |||
| 4108 | skillsButton->setText(Language::get(4117)); | |||
| 4109 | skillsButton->setFont(buttonFont); | |||
| 4110 | skillsButton->setBackground("*#images/ui/HUD/HUD_Button_Base_Small_00.png"); | |||
| 4111 | skillsButton->setBackgroundActivated("*#images/ui/HUD/HUD_Button_Base_SmallPress_00.png"); | |||
| 4112 | skillsButton->setBackgroundHighlighted("*#images/ui/HUD/HUD_Button_Base_SmallHigh_00.png"); | |||
| 4113 | skillsButton->setSize(SDL_Rect{ 0, 0, 98, 38 }); | |||
| 4114 | skillsButton->setHideGlyphs(true); | |||
| 4115 | skillsButton->setHideKeyboardGlyphs(true); | |||
| 4116 | skillsButton->setHideSelectors(true); | |||
| 4117 | skillsButton->setMenuConfirmControlType(0); | |||
| 4118 | skillsButton->setColor(makeColor(255, 255, 255, 255)); | |||
| 4119 | skillsButton->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 4120 | skillsButton->setCallback([](Button& button) { | |||
| 4121 | players[button.getOwner()]->skillSheet.openSkillSheet(); | |||
| 4122 | }); | |||
| 4123 | ||||
| 4124 | auto skillsButtonGlyph = uiNavFrame->addImage(SDL_Rect{ 0, 0, glyphSize, glyphSize }, | |||
| 4125 | 0xFFFFFFFF, "images/system/white.png", "skills button glyph")->disabled = true; | |||
| 4126 | } | |||
| 4127 | { | |||
| 4128 | const int glyphSize = 32; | |||
| 4129 | const char* navFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 4130 | auto leftBumperNavigationTxt = uiNavFrame->addField("left bumper txt", 64); | |||
| 4131 | leftBumperNavigationTxt->setFont(navFont); | |||
| 4132 | leftBumperNavigationTxt->setHJustify(Field::justify_t::RIGHT); | |||
| 4133 | leftBumperNavigationTxt->setVJustify(Field::justify_t::CENTER); | |||
| 4134 | leftBumperNavigationTxt->setDisabled(true); | |||
| 4135 | ||||
| 4136 | auto leftBumperNavigationImg = uiNavFrame->addImage(SDL_Rect{ 0, 0, glyphSize, glyphSize }, | |||
| 4137 | 0xFFFFFFFF, "images/system/white.png", "left bumper img"); | |||
| 4138 | leftBumperNavigationImg->disabled = true; | |||
| 4139 | ||||
| 4140 | auto rightBumperNavigationTxt = uiNavFrame->addField("right bumper txt", 64); | |||
| 4141 | rightBumperNavigationTxt->setFont(navFont); | |||
| 4142 | rightBumperNavigationTxt->setVJustify(Field::justify_t::CENTER); | |||
| 4143 | rightBumperNavigationTxt->setHJustify(Field::justify_t::LEFT); | |||
| 4144 | ||||
| 4145 | auto rightBumperNavigationImg = uiNavFrame->addImage(SDL_Rect{ 0, 0, glyphSize, glyphSize }, | |||
| 4146 | 0xFFFFFFFF, "images/system/white.png", "right bumper img"); | |||
| 4147 | rightBumperNavigationImg->disabled = true; | |||
| 4148 | ||||
| 4149 | auto leftTriggerNavigationTxt = uiNavFrame->addField("left trigger txt", 64); | |||
| 4150 | leftTriggerNavigationTxt->setFont(navFont); | |||
| 4151 | leftTriggerNavigationTxt->setHJustify(Field::justify_t::RIGHT); | |||
| 4152 | leftTriggerNavigationTxt->setVJustify(Field::justify_t::CENTER); | |||
| 4153 | leftTriggerNavigationTxt->setDisabled(true); | |||
| 4154 | ||||
| 4155 | auto leftTriggerNavigationImg = uiNavFrame->addImage(SDL_Rect{ 0, 0, glyphSize, glyphSize }, | |||
| 4156 | 0xFFFFFFFF, "images/system/white.png", "left trigger img"); | |||
| 4157 | leftTriggerNavigationImg->disabled = true; | |||
| 4158 | ||||
| 4159 | auto rightTriggerNavigationTxt = uiNavFrame->addField("right trigger txt", 64); | |||
| 4160 | rightTriggerNavigationTxt->setFont(navFont); | |||
| 4161 | rightTriggerNavigationTxt->setVJustify(Field::justify_t::CENTER); | |||
| 4162 | rightTriggerNavigationTxt->setHJustify(Field::justify_t::LEFT); | |||
| 4163 | ||||
| 4164 | auto rightTriggerNavigationImg = uiNavFrame->addImage(SDL_Rect{ 0, 0, glyphSize, glyphSize }, | |||
| 4165 | 0xFFFFFFFF, "images/system/white.png", "right trigger img"); | |||
| 4166 | rightTriggerNavigationImg->disabled = true; | |||
| 4167 | ||||
| 4168 | auto additionalNavigationTxt = uiNavFrame->addField("additional txt", 64); | |||
| 4169 | additionalNavigationTxt->setFont(navFont); | |||
| 4170 | additionalNavigationTxt->setVJustify(Field::justify_t::CENTER); | |||
| 4171 | additionalNavigationTxt->setHJustify(Field::justify_t::LEFT); | |||
| 4172 | ||||
| 4173 | auto additionalNavigationImg = uiNavFrame->addImage(SDL_Rect{ 0, 0, glyphSize, glyphSize }, | |||
| 4174 | 0xFFFFFFFF, "images/system/white.png", "additional img"); | |||
| 4175 | additionalNavigationImg->disabled = true; | |||
| 4176 | } | |||
| 4177 | } | |||
| 4178 | ||||
| 4179 | void Player::HUD_t::updateUINavigation() | |||
| 4180 | { | |||
| 4181 | if ( !hudFrame ) | |||
| 4182 | { | |||
| 4183 | return; | |||
| 4184 | } | |||
| 4185 | ||||
| 4186 | if ( !uiNavFrame ) | |||
| 4187 | { | |||
| 4188 | createUINavigation(player.playernum); | |||
| 4189 | if ( !uiNavFrame ) | |||
| 4190 | { | |||
| 4191 | return; | |||
| 4192 | } | |||
| 4193 | } | |||
| 4194 | ||||
| 4195 | bool leftTriggerPressed = Input::inputs[player.playernum].consumeBinaryToggle("UINavLeftTrigger") | |||
| 4196 | && player.bControlEnabled && !gamePaused && !player.usingCommand(); | |||
| 4197 | bool rightTriggerPressed = Input::inputs[player.playernum].consumeBinaryToggle("UINavRightTrigger") | |||
| 4198 | && player.bControlEnabled && !gamePaused && !player.usingCommand(); | |||
| 4199 | ||||
| 4200 | bShowUINavigation = false; | |||
| 4201 | if ( player.gui_mode != GUI_MODE_NONE | |||
| 4202 | && player.gui_mode != GUI_MODE_FOLLOWERMENU | |||
| 4203 | && player.gui_mode != GUI_MODE_CALLOUT | |||
| 4204 | && player.gui_mode != GUI_MODE_SIGN | |||
| 4205 | && player.isLocalPlayer() && !player.shootmode ) | |||
| 4206 | { | |||
| 4207 | /*if ( player.bUseCompactGUIHeight() * Frame::virtualScreenX || (keystatus[SDLK_Y] && enableDebugKeys) ) | |||
| 4208 | { | |||
| 4209 | bShowUINavigation = true; | |||
| 4210 | }*/ | |||
| 4211 | bShowUINavigation = true; | |||
| 4212 | } | |||
| 4213 | ||||
| 4214 | if ( !bShowUINavigation ) | |||
| 4215 | { | |||
| 4216 | uiNavFrame->setDisabled(true); | |||
| 4217 | return; | |||
| 4218 | } | |||
| 4219 | uiNavFrame->setDisabled(false); | |||
| 4220 | uiNavFrame->setSize(SDL_Rect{ 0, 0, hudFrame->getSize().w, hudFrame->getSize().h }); | |||
| 4221 | ||||
| 4222 | if ( player.bUseCompactGUIWidth() && | |||
| 4223 | (player.hud.levelupFrame && !player.hud.levelupFrame->isDisabled()) ) | |||
| 4224 | { | |||
| 4225 | uiNavFrame->setInvisible(true); | |||
| 4226 | } | |||
| 4227 | else | |||
| 4228 | { | |||
| 4229 | uiNavFrame->setInvisible(false); | |||
| 4230 | } | |||
| 4231 | ||||
| 4232 | auto leftBumperModule = player.GUI.handleModuleNavigation(true, true); | |||
| 4233 | auto leftBumperTxt = uiNavFrame->findField("left bumper txt"); | |||
| 4234 | leftBumperTxt->setDisabled(true); | |||
| 4235 | auto leftBumperGlyph = uiNavFrame->findImage("left bumper img"); | |||
| 4236 | leftBumperGlyph->disabled = true; | |||
| 4237 | auto rightBumperModule = player.GUI.handleModuleNavigation(true, false); | |||
| 4238 | auto rightBumperTxt = uiNavFrame->findField("right bumper txt"); | |||
| 4239 | rightBumperTxt->setDisabled(true); | |||
| 4240 | auto rightBumperGlyph = uiNavFrame->findImage("right bumper img"); | |||
| 4241 | rightBumperGlyph->disabled = true; | |||
| 4242 | ||||
| 4243 | auto leftTriggerTxt = uiNavFrame->findField("left trigger txt"); | |||
| 4244 | leftTriggerTxt->setDisabled(true); | |||
| 4245 | auto leftTriggerGlyph = uiNavFrame->findImage("left trigger img"); | |||
| 4246 | leftTriggerGlyph->disabled = true; | |||
| 4247 | auto rightTriggerTxt = uiNavFrame->findField("right trigger txt"); | |||
| 4248 | rightTriggerTxt->setDisabled(true); | |||
| 4249 | auto rightTriggerGlyph = uiNavFrame->findImage("right trigger img"); | |||
| 4250 | rightTriggerGlyph->disabled = true; | |||
| 4251 | ||||
| 4252 | auto additionalTxt = uiNavFrame->findField("additional txt"); | |||
| 4253 | additionalTxt->setDisabled(true); | |||
| 4254 | auto additionalGlyph = uiNavFrame->findImage("additional img"); | |||
| 4255 | additionalGlyph->disabled = true; | |||
| 4256 | if ( inputs.hasController(player.playernum) && !inputs.getVirtualMouse(player.playernum)->draw_cursor | |||
| 4257 | && (!player.bUseCompactGUIHeight() && !player.bUseCompactGUIWidth()) ) | |||
| 4258 | { | |||
| 4259 | if ( leftBumperModule != Player::GUI_t::MODULE_NONE ) | |||
| 4260 | { | |||
| 4261 | switch ( leftBumperModule ) | |||
| 4262 | { | |||
| 4263 | case Player::GUI_t::MODULE_INVENTORY: | |||
| 4264 | case Player::GUI_t::MODULE_SPELLS: | |||
| 4265 | case Player::GUI_t::MODULE_HOTBAR: | |||
| 4266 | case Player::GUI_t::MODULE_CHARACTERSHEET: | |||
| 4267 | case Player::GUI_t::MODULE_CHEST: | |||
| 4268 | case Player::GUI_t::MODULE_SHOP: | |||
| 4269 | case Player::GUI_t::MODULE_ALCHEMY: | |||
| 4270 | leftBumperTxt->setDisabled(false); | |||
| 4271 | leftBumperTxt->setText("/"); | |||
| 4272 | break; | |||
| 4273 | default: | |||
| 4274 | break; | |||
| 4275 | } | |||
| 4276 | } | |||
| 4277 | if ( rightBumperModule != Player::GUI_t::MODULE_NONE ) | |||
| 4278 | { | |||
| 4279 | switch ( rightBumperModule ) | |||
| 4280 | { | |||
| 4281 | case Player::GUI_t::MODULE_INVENTORY: | |||
| 4282 | case Player::GUI_t::MODULE_SPELLS: | |||
| 4283 | case Player::GUI_t::MODULE_HOTBAR: | |||
| 4284 | case Player::GUI_t::MODULE_CHARACTERSHEET: | |||
| 4285 | case Player::GUI_t::MODULE_CHEST: | |||
| 4286 | case Player::GUI_t::MODULE_SHOP: | |||
| 4287 | case Player::GUI_t::MODULE_ALCHEMY: | |||
| 4288 | rightBumperTxt->setDisabled(false); | |||
| 4289 | rightBumperTxt->setText(Language::get(4092)); | |||
| 4290 | break; | |||
| 4291 | default: | |||
| 4292 | break; | |||
| 4293 | } | |||
| 4294 | } | |||
| 4295 | if ( player.GUI.activeModule == Player::GUI_t::MODULE_INVENTORY || player.GUI.activeModule == Player::GUI_t::MODULE_HOTBAR ) | |||
| 4296 | { | |||
| 4297 | ||||
| 4298 | } | |||
| 4299 | else if ( player.GUI.activeModule == Player::GUI_t::MODULE_CHARACTERSHEET ) | |||
| 4300 | { | |||
| 4301 | auto selectedElement = player.characterSheet.selectedElement; | |||
| 4302 | if ( selectedElement >= Player::CharacterSheet_t::SHEET_STR | |||
| 4303 | && selectedElement <= Player::CharacterSheet_t::SHEET_WGT ) | |||
| 4304 | { | |||
| 4305 | additionalTxt->setDisabled(false); | |||
| 4306 | additionalTxt->setText(Language::get(4111)); | |||
| 4307 | } | |||
| 4308 | else if ( selectedElement == Player::CharacterSheet_t::SHEET_CHAR_RACE_SEX | |||
| 4309 | || selectedElement == Player::CharacterSheet_t::SHEET_CHAR_CLASS ) | |||
| 4310 | { | |||
| 4311 | additionalTxt->setDisabled(false); | |||
| 4312 | additionalTxt->setText(Language::get(4111)); | |||
| 4313 | } | |||
| 4314 | else if ( selectedElement == Player::CharacterSheet_t::SHEET_DUNGEON_FLOOR ) | |||
| 4315 | { | |||
| 4316 | additionalTxt->setDisabled(false); | |||
| 4317 | additionalTxt->setText(Language::get(4112)); | |||
| 4318 | } | |||
| 4319 | else if ( selectedElement == Player::CharacterSheet_t::SHEET_SKILL_LIST | |||
| 4320 | || selectedElement == Player::CharacterSheet_t::SHEET_OPEN_LOG | |||
| 4321 | || selectedElement == Player::CharacterSheet_t::SHEET_OPEN_MAP ) | |||
| 4322 | { | |||
| 4323 | additionalTxt->setDisabled(false); | |||
| 4324 | // options to use specific text 'open log' etc | |||
| 4325 | //if ( selectedElement == Player::CharacterSheet_t::SHEET_SKILL_LIST ) | |||
| 4326 | //{ | |||
| 4327 | // additionalTxt->setText(Language::get(4095)); | |||
| 4328 | //} | |||
| 4329 | //else if ( selectedElement == Player::CharacterSheet_t::SHEET_OPEN_LOG ) | |||
| 4330 | //{ | |||
| 4331 | // additionalTxt->setText(Language::get(4106)); | |||
| 4332 | //} | |||
| 4333 | //else if ( selectedElement == Player::CharacterSheet_t::SHEET_OPEN_MAP ) | |||
| 4334 | //{ | |||
| 4335 | // additionalTxt->setText(Language::get(4105)); | |||
| 4336 | //} | |||
| 4337 | additionalTxt->setText(Language::get(4107)); // activate | |||
| 4338 | } | |||
| 4339 | else if ( selectedElement == Player::CharacterSheet_t::SHEET_GOLD ) | |||
| 4340 | { | |||
| 4341 | additionalTxt->setDisabled(false); | |||
| 4342 | if ( player.GUI.isDropdownActive() ) | |||
| 4343 | { | |||
| 4344 | additionalTxt->setText(Language::get(4053)); | |||
| 4345 | } | |||
| 4346 | else | |||
| 4347 | { | |||
| 4348 | additionalTxt->setText(Language::get(4108)); | |||
| 4349 | } | |||
| 4350 | } | |||
| 4351 | else if ( selectedElement == Player::CharacterSheet_t::SHEET_TIMER ) | |||
| 4352 | { | |||
| 4353 | additionalTxt->setDisabled(false); | |||
| 4354 | if ( player.characterSheet.showGameTimerAlways ) | |||
| 4355 | { | |||
| 4356 | additionalTxt->setText(Language::get(4110)); | |||
| 4357 | } | |||
| 4358 | else | |||
| 4359 | { | |||
| 4360 | additionalTxt->setText(Language::get(4109)); | |||
| 4361 | } | |||
| 4362 | } | |||
| 4363 | if ( !additionalTxt->isDisabled() ) | |||
| 4364 | { | |||
| 4365 | if ( selectedElement == Player::CharacterSheet_t::SHEET_GOLD | |||
| 4366 | && player.GUI.isDropdownActive() ) | |||
| 4367 | { | |||
| 4368 | additionalGlyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("MenuCancel"); | |||
| 4369 | } | |||
| 4370 | else | |||
| 4371 | { | |||
| 4372 | additionalGlyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("MenuConfirm"); | |||
| 4373 | } | |||
| 4374 | } | |||
| 4375 | } | |||
| 4376 | } | |||
| 4377 | ||||
| 4378 | int lowestLeftY = 8; | |||
| 4379 | int lowestRightY = 8; | |||
| 4380 | ||||
| 4381 | int leftAnchorX = 0; | |||
| 4382 | int rightAnchorX = 0; | |||
| 4383 | PanelJustify_t justify = player.inventoryUI.inventoryPanelJustify; | |||
| 4384 | if ( player.inventoryUI.frame ) | |||
| 4385 | { | |||
| 4386 | auto inventoryBgFrame = player.inventoryUI.frame->findFrame("inventory base"); | |||
| 4387 | ||||
| 4388 | Frame::image_t* invBaseImg = inventoryBgFrame->findImage("inventory base img"); | |||
| 4389 | ||||
| 4390 | if ( justify == PANEL_JUSTIFY_LEFT ) | |||
| 4391 | { | |||
| 4392 | leftAnchorX = inventoryBgFrame->getSize().x + 8; | |||
| 4393 | leftAnchorX += invBaseImg->pos.w; | |||
| 4394 | ||||
| 4395 | rightAnchorX = player.inventoryUI.frame->getSize().w - leftAnchorX; | |||
| 4396 | } | |||
| 4397 | else | |||
| 4398 | { | |||
| 4399 | rightAnchorX = inventoryBgFrame->getSize().x - 8; | |||
| 4400 | rightAnchorX += invBaseImg->pos.x; | |||
| 4401 | ||||
| 4402 | leftAnchorX = player.inventoryUI.frame->getSize().w - rightAnchorX; | |||
| 4403 | } | |||
| 4404 | } | |||
| 4405 | ||||
| 4406 | if ( inputs.hasController(player.playernum) && !inputs.getVirtualMouse(player.playernum)->draw_cursor | |||
| 4407 | && (!player.bUseCompactGUIHeight() && !player.bUseCompactGUIWidth()) ) | |||
| 4408 | { | |||
| 4409 | if ( (player.GUI.activeModule == Player::GUI_t::MODULE_INVENTORY | |||
| 4410 | || player.GUI.activeModule == Player::GUI_t::MODULE_SPELLS | |||
| 4411 | || player.GUI.activeModule == Player::GUI_t::MODULE_HOTBAR | |||
| 4412 | || player.GUI.activeModule == Player::GUI_t::MODULE_CHARACTERSHEET | |||
| 4413 | || player.GUI.activeModule == Player::GUI_t::MODULE_SHOP | |||
| 4414 | || player.GUI.activeModule == Player::GUI_t::MODULE_CHEST) ) | |||
| 4415 | { | |||
| 4416 | if ( !GenericGUI[player.playernum].tinkerGUI.bOpen && !GenericGUI[player.playernum].alchemyGUI.bOpen | |||
| 4417 | && !GenericGUI[player.playernum].featherGUI.bOpen | |||
| 4418 | && !GenericGUI[player.playernum].itemfxGUI.bOpen ) | |||
| 4419 | { | |||
| 4420 | justify = PANEL_JUSTIFY_LEFT; | |||
| 4421 | leftTriggerGlyph->disabled = false; | |||
| 4422 | leftTriggerGlyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("UINavLeftTrigger"); | |||
| 4423 | SDL_Rect textPos; | |||
| 4424 | textPos.x = (justify == PANEL_JUSTIFY_LEFT) ? leftAnchorX : rightAnchorX; | |||
| 4425 | textPos.y = 8; | |||
| 4426 | textPos.w = leftTriggerTxt->getTextObject()->getWidth(); | |||
| 4427 | textPos.h = Font::get(leftTriggerTxt->getFont())->height() + 8; | |||
| 4428 | if ( justify == PANEL_JUSTIFY_LEFT ) | |||
| 4429 | { | |||
| 4430 | leftTriggerTxt->setHJustify(Field::justify_t::LEFT); | |||
| 4431 | } | |||
| 4432 | else | |||
| 4433 | { | |||
| 4434 | leftTriggerTxt->setHJustify(Field::justify_t::RIGHT); | |||
| 4435 | } | |||
| 4436 | ||||
| 4437 | SDL_Rect imgPos{0, 0, 0, 0}; | |||
| 4438 | if ( auto imgGet = Image::get(leftTriggerGlyph->path.c_str()) ) | |||
| 4439 | { | |||
| 4440 | imgPos.w = imgGet->getWidth(); | |||
| 4441 | imgPos.h = imgGet->getHeight(); | |||
| 4442 | } | |||
| 4443 | imgPos.x = (justify == PANEL_JUSTIFY_LEFT) ? leftAnchorX : rightAnchorX; | |||
| 4444 | imgPos.y = textPos.y - (imgPos.h - textPos.h) / 2; | |||
| 4445 | ||||
| 4446 | if ( justify == PANEL_JUSTIFY_LEFT ) | |||
| 4447 | { | |||
| 4448 | leftTriggerGlyph->pos = imgPos; | |||
| 4449 | textPos.x = leftTriggerGlyph->pos.x + leftTriggerGlyph->pos.w + 8; | |||
| 4450 | leftTriggerTxt->setSize(textPos); | |||
| 4451 | } | |||
| 4452 | else | |||
| 4453 | { | |||
| 4454 | imgPos.x -= imgPos.w; | |||
| 4455 | leftTriggerGlyph->pos = imgPos; | |||
| 4456 | textPos.x = leftTriggerGlyph->pos.x - 8 - textPos.w; | |||
| 4457 | leftTriggerTxt->setSize(textPos); | |||
| 4458 | } | |||
| 4459 | leftTriggerTxt->setDisabled(false); | |||
| 4460 | if ( player.inventory_mode == INVENTORY_MODE_ITEM ) | |||
| 4461 | { | |||
| 4462 | leftTriggerTxt->setText(Language::get(4093)); | |||
| 4463 | } | |||
| 4464 | else if ( player.inventory_mode == INVENTORY_MODE_SPELL ) | |||
| 4465 | { | |||
| 4466 | leftTriggerTxt->setText(Language::get(4094)); | |||
| 4467 | } | |||
| 4468 | } | |||
| 4469 | ||||
| 4470 | if ( !player.inventoryUI.chestGUI.bOpen && !player.shopGUI.bOpen | |||
| 4471 | && !GenericGUI[player.playernum].tinkerGUI.bOpen && !GenericGUI[player.playernum].alchemyGUI.bOpen | |||
| 4472 | && !GenericGUI[player.playernum].featherGUI.bOpen | |||
| 4473 | && !GenericGUI[player.playernum].itemfxGUI.bOpen ) | |||
| 4474 | { | |||
| 4475 | justify = PANEL_JUSTIFY_RIGHT; | |||
| 4476 | rightTriggerGlyph->disabled = false; | |||
| 4477 | rightTriggerGlyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("UINavRightTrigger"); | |||
| 4478 | SDL_Rect textPos; | |||
| 4479 | textPos.x = (justify == PANEL_JUSTIFY_LEFT) ? leftAnchorX : rightAnchorX; | |||
| 4480 | textPos.y = 8; | |||
| 4481 | textPos.w = rightTriggerTxt->getTextObject()->getWidth(); | |||
| 4482 | textPos.h = Font::get(rightTriggerTxt->getFont())->height() + 8; | |||
| 4483 | if ( justify == PANEL_JUSTIFY_LEFT ) | |||
| 4484 | { | |||
| 4485 | rightTriggerTxt->setHJustify(Field::justify_t::LEFT); | |||
| 4486 | } | |||
| 4487 | else | |||
| 4488 | { | |||
| 4489 | rightTriggerTxt->setHJustify(Field::justify_t::RIGHT); | |||
| 4490 | } | |||
| 4491 | ||||
| 4492 | SDL_Rect imgPos{ 0, 0, 0, 0 }; | |||
| 4493 | if ( auto imgGet = Image::get(rightTriggerGlyph->path.c_str()) ) | |||
| 4494 | { | |||
| 4495 | imgPos.w = imgGet->getWidth(); | |||
| 4496 | imgPos.h = imgGet->getHeight(); | |||
| 4497 | } | |||
| 4498 | imgPos.x = (justify == PANEL_JUSTIFY_LEFT) ? leftAnchorX : rightAnchorX; | |||
| 4499 | imgPos.y = textPos.y - (imgPos.h - textPos.h) / 2; | |||
| 4500 | ||||
| 4501 | if ( justify == PANEL_JUSTIFY_LEFT ) | |||
| 4502 | { | |||
| 4503 | rightTriggerGlyph->pos = imgPos; | |||
| 4504 | textPos.x = rightTriggerGlyph->pos.x + rightTriggerGlyph->pos.w + 8; | |||
| 4505 | rightTriggerTxt->setSize(textPos); | |||
| 4506 | } | |||
| 4507 | else | |||
| 4508 | { | |||
| 4509 | imgPos.x -= imgPos.w; | |||
| 4510 | rightTriggerGlyph->pos = imgPos; | |||
| 4511 | textPos.x = rightTriggerGlyph->pos.x - 8 - textPos.w; | |||
| 4512 | rightTriggerTxt->setSize(textPos); | |||
| 4513 | } | |||
| 4514 | rightTriggerTxt->setDisabled(false); | |||
| 4515 | rightTriggerTxt->setText(Language::get(4095)); | |||
| 4516 | ||||
| 4517 | if ( !additionalTxt->isDisabled() ) | |||
| 4518 | { | |||
| 4519 | if ( justify == PANEL_JUSTIFY_LEFT ) | |||
| 4520 | { | |||
| 4521 | additionalTxt->setHJustify(Field::justify_t::LEFT); | |||
| 4522 | } | |||
| 4523 | else | |||
| 4524 | { | |||
| 4525 | additionalTxt->setHJustify(Field::justify_t::RIGHT); | |||
| 4526 | } | |||
| 4527 | additionalGlyph->disabled = false; | |||
| 4528 | SDL_Rect textPos; | |||
| 4529 | textPos.w = additionalTxt->getTextObject()->getWidth(); | |||
| 4530 | textPos.h = Font::get(additionalTxt->getFont())->height() + 8; | |||
| 4531 | if ( justify == PANEL_JUSTIFY_LEFT ) | |||
| 4532 | { | |||
| 4533 | textPos.x = rightTriggerTxt->getSize().x; | |||
| 4534 | } | |||
| 4535 | else | |||
| 4536 | { | |||
| 4537 | textPos.x = rightTriggerTxt->getSize().x + rightTriggerTxt->getSize().w - textPos.w; | |||
| 4538 | } | |||
| 4539 | textPos.y = std::max(lowestRightY, rightTriggerTxt->getSize().y + rightTriggerTxt->getSize().h); | |||
| 4540 | ||||
| 4541 | SDL_Rect imgPos{ 0, 0, 0, 0 }; | |||
| 4542 | if ( auto imgGet = Image::get(additionalGlyph->path.c_str()) ) | |||
| 4543 | { | |||
| 4544 | imgPos.w = imgGet->getWidth(); | |||
| 4545 | imgPos.h = imgGet->getHeight(); | |||
| 4546 | } | |||
| 4547 | imgPos.x = rightTriggerGlyph->pos.x + rightTriggerGlyph->pos.w / 2 - imgPos.w / 2; | |||
| 4548 | imgPos.y = textPos.y - (imgPos.h - textPos.h) / 2; | |||
| 4549 | additionalGlyph->pos = imgPos; | |||
| 4550 | ||||
| 4551 | additionalTxt->setSize(textPos); | |||
| 4552 | } | |||
| 4553 | } | |||
| 4554 | } | |||
| 4555 | ||||
| 4556 | if ( leftTriggerPressed && !leftTriggerTxt->isDisabled() ) | |||
| 4557 | { | |||
| 4558 | leftTriggerPressed = false; | |||
| 4559 | if ( !inputs.getUIInteraction(player.playernum)->selectedItem && !player.GUI.isDropdownActive() | |||
| 4560 | && (inputs.hasController(player.playernum) && !player.shootmode | |||
| 4561 | && (player.GUI.activeModule == Player::GUI_t::MODULE_INVENTORY | |||
| 4562 | || player.GUI.activeModule == Player::GUI_t::MODULE_SPELLS | |||
| 4563 | || player.GUI.activeModule == Player::GUI_t::MODULE_HOTBAR | |||
| 4564 | || player.GUI.activeModule == Player::GUI_t::MODULE_CHARACTERSHEET | |||
| 4565 | || player.GUI.activeModule == Player::GUI_t::MODULE_CHEST | |||
| 4566 | || player.GUI.activeModule == Player::GUI_t::MODULE_SHOP)) ) | |||
| 4567 | { | |||
| 4568 | player.gui_mode = GUI_MODE_INVENTORY; | |||
| 4569 | if ( player.shootmode ) | |||
| 4570 | { | |||
| 4571 | player.openStatusScreen(GUI_MODE_INVENTORY, INVENTORY_MODE_ITEM); | |||
| 4572 | } | |||
| 4573 | player.inventoryUI.cycleInventoryTab(); | |||
| 4574 | } | |||
| 4575 | } | |||
| 4576 | ||||
| 4577 | if ( rightTriggerPressed && !rightTriggerTxt->isDisabled() ) | |||
| 4578 | { | |||
| 4579 | rightTriggerPressed = false; | |||
| 4580 | if ( !inputs.getUIInteraction(player.playernum)->selectedItem && !player.GUI.isDropdownActive() | |||
| 4581 | && (inputs.hasController(player.playernum) && !player.shootmode | |||
| 4582 | && (player.GUI.activeModule == Player::GUI_t::MODULE_INVENTORY | |||
| 4583 | || player.GUI.activeModule == Player::GUI_t::MODULE_SPELLS | |||
| 4584 | || player.GUI.activeModule == Player::GUI_t::MODULE_HOTBAR | |||
| 4585 | || player.GUI.activeModule == Player::GUI_t::MODULE_CHARACTERSHEET)) ) | |||
| 4586 | { | |||
| 4587 | if ( !player.skillSheet.bSkillSheetOpen ) | |||
| 4588 | { | |||
| 4589 | player.skillSheet.openSkillSheet(); | |||
| 4590 | } | |||
| 4591 | } | |||
| 4592 | } | |||
| 4593 | ||||
| 4594 | if ( !leftTriggerTxt->isDisabled() ) | |||
| 4595 | { | |||
| 4596 | lowestLeftY = std::max(lowestLeftY, leftTriggerTxt->getSize().y + leftTriggerTxt->getSize().h); | |||
| 4597 | lowestLeftY = std::max(lowestLeftY, leftTriggerGlyph->pos.y + leftTriggerGlyph->pos.h); | |||
| 4598 | } | |||
| 4599 | if ( !rightTriggerTxt->isDisabled() ) | |||
| 4600 | { | |||
| 4601 | lowestRightY = std::max(lowestRightY, rightTriggerTxt->getSize().y + rightTriggerTxt->getSize().h); | |||
| 4602 | lowestRightY = std::max(lowestRightY, rightTriggerGlyph->pos.y + rightTriggerGlyph->pos.h); | |||
| 4603 | } | |||
| 4604 | ||||
| 4605 | if ( !leftBumperTxt->isDisabled() ) | |||
| 4606 | { | |||
| 4607 | leftBumperGlyph->disabled = false; | |||
| 4608 | leftBumperGlyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("UINavLeftBumper"); | |||
| 4609 | SDL_Rect textPos; | |||
| 4610 | textPos.x = leftTriggerGlyph->pos.x; | |||
| 4611 | textPos.y = lowestLeftY; | |||
| 4612 | textPos.w = leftBumperTxt->getTextObject()->getWidth(); | |||
| 4613 | textPos.h = Font::get(leftBumperTxt->getFont())->height() + 8; | |||
| 4614 | ||||
| 4615 | SDL_Rect imgPos{ 0, 0, 0, 0 }; | |||
| 4616 | if ( auto imgGet = Image::get(leftBumperGlyph->path.c_str()) ) | |||
| 4617 | { | |||
| 4618 | imgPos.w = imgGet->getWidth(); | |||
| 4619 | imgPos.h = imgGet->getHeight(); | |||
| 4620 | } | |||
| 4621 | imgPos.x = textPos.x; | |||
| 4622 | imgPos.y = textPos.y - (imgPos.h - textPos.h) / 2; | |||
| 4623 | leftBumperGlyph->pos = imgPos; | |||
| 4624 | ||||
| 4625 | textPos.x = imgPos.x + 4 + imgPos.w; | |||
| 4626 | leftBumperTxt->setSize(textPos); | |||
| 4627 | } | |||
| 4628 | if ( !rightBumperTxt->isDisabled() ) | |||
| 4629 | { | |||
| 4630 | rightBumperGlyph->disabled = false; | |||
| 4631 | rightBumperGlyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("UINavRightBumper"); | |||
| 4632 | SDL_Rect textPos; | |||
| 4633 | textPos.x = leftBumperTxt->getSize().x + leftBumperTxt->getSize().w + 8; | |||
| 4634 | textPos.y = leftBumperTxt->getSize().y; | |||
| 4635 | textPos.w = rightBumperTxt->getTextObject()->getWidth(); | |||
| 4636 | textPos.h = Font::get(rightBumperTxt->getFont())->height() + 8; | |||
| 4637 | ||||
| 4638 | SDL_Rect imgPos{ 0, 0, 0, 0 }; | |||
| 4639 | if ( auto imgGet = Image::get(rightBumperGlyph->path.c_str()) ) | |||
| 4640 | { | |||
| 4641 | imgPos.w = imgGet->getWidth(); | |||
| 4642 | imgPos.h = imgGet->getHeight(); | |||
| 4643 | } | |||
| 4644 | imgPos.x = textPos.x; | |||
| 4645 | imgPos.y = textPos.y - (imgPos.h - textPos.h) / 2; | |||
| 4646 | ||||
| 4647 | textPos.x += imgPos.w + 4; | |||
| 4648 | rightBumperTxt->setSize(textPos); | |||
| 4649 | rightBumperGlyph->pos = imgPos; | |||
| 4650 | } | |||
| 4651 | } | |||
| 4652 | ||||
| 4653 | auto magicButton = uiNavFrame->findButton("magic button"); | |||
| 4654 | auto magicButtonGlyph = uiNavFrame->findImage("magic button glyph"); | |||
| 4655 | auto itemsButton = uiNavFrame->findButton("items button"); | |||
| 4656 | auto itemsButtonGlyph = uiNavFrame->findImage("items button glyph"); | |||
| 4657 | auto statusButton = uiNavFrame->findButton("status button"); | |||
| 4658 | auto statusButtonGlyph = uiNavFrame->findImage("status button glyph"); | |||
| 4659 | auto skillsButton = uiNavFrame->findButton("skills button"); | |||
| 4660 | auto skillsButtonGlyph = uiNavFrame->findImage("skills button glyph"); | |||
| 4661 | ||||
| 4662 | static ConsoleVariable<bool> cvar_spell_unread_blink("/spell_unread_blink", true); | |||
| 4663 | if ( *cvar_spell_unread_blink | |||
| 4664 | && player.magic.bHasUnreadNewSpell && ticks % TICKS_PER_SECOND50 >= TICKS_PER_SECOND50 / 2 ) | |||
| 4665 | { | |||
| 4666 | magicButton->setTextColor(hudColors.characterSheetGreen); | |||
| 4667 | magicButton->setTextHighlightColor(hudColors.characterSheetGreen); | |||
| 4668 | } | |||
| 4669 | else | |||
| 4670 | { | |||
| 4671 | magicButton->setTextColor(makeColor(255, 255, 255, 255)); | |||
| 4672 | magicButton->setTextHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 4673 | } | |||
| 4674 | ||||
| 4675 | struct ButtonsAndGlyphs { | |||
| 4676 | std::string name; | |||
| 4677 | Button* button = nullptr; | |||
| 4678 | Frame::image_t* glyph = nullptr; | |||
| 4679 | std::string inputName; | |||
| 4680 | CompactLayoutModes layoutMode; | |||
| 4681 | ButtonsAndGlyphs(std::string _name, | |||
| 4682 | Button* _button, | |||
| 4683 | Frame::image_t* _glyph, | |||
| 4684 | std::string _inputName, | |||
| 4685 | CompactLayoutModes _layoutMode) : | |||
| 4686 | name(_name), | |||
| 4687 | button(_button), | |||
| 4688 | glyph(_glyph), | |||
| 4689 | inputName(_inputName), | |||
| 4690 | layoutMode(_layoutMode) | |||
| 4691 | { | |||
| 4692 | } | |||
| 4693 | }; | |||
| 4694 | std::vector<ButtonsAndGlyphs> allButtonsAndGlyphs; | |||
| 4695 | allButtonsAndGlyphs.emplace_back( | |||
| 4696 | ButtonsAndGlyphs{ "magic button", magicButton, magicButtonGlyph, | |||
| 4697 | "UINavLeftTrigger", COMPACT_LAYOUT_INVENTORY }); | |||
| 4698 | allButtonsAndGlyphs.emplace_back( | |||
| 4699 | ButtonsAndGlyphs{ "status button", statusButton, statusButtonGlyph, | |||
| 4700 | "UINavRightTrigger", COMPACT_LAYOUT_INVENTORY }); | |||
| 4701 | allButtonsAndGlyphs.emplace_back( | |||
| 4702 | ButtonsAndGlyphs{ "items button", itemsButton, itemsButtonGlyph, | |||
| 4703 | "UINavLeftTrigger", COMPACT_LAYOUT_CHARSHEET }); | |||
| 4704 | allButtonsAndGlyphs.emplace_back( | |||
| 4705 | ButtonsAndGlyphs{ "skills button", skillsButton, skillsButtonGlyph, | |||
| 4706 | "UINavRightTrigger", COMPACT_LAYOUT_CHARSHEET }); | |||
| 4707 | ||||
| 4708 | int buttonWidth = 98; | |||
| 4709 | int buttonHeight = 38; | |||
| 4710 | int alignPaddingX = 2; | |||
| 4711 | int leftAlignX = uiNavFrame->getSize().w / 2 - buttonWidth - alignPaddingX; | |||
| 4712 | int rightAlignX = uiNavFrame->getSize().w / 2 + alignPaddingX; | |||
| 4713 | int topAlignY = 34; | |||
| 4714 | int bottomAlignY = topAlignY + 52; | |||
| 4715 | ||||
| 4716 | int numButtonsToShow = 2; | |||
| 4717 | ||||
| 4718 | for ( auto& buttonAndGlyph : allButtonsAndGlyphs ) | |||
| 4719 | { | |||
| 4720 | auto& button = buttonAndGlyph.button; | |||
| 4721 | button->setDisabled(true); | |||
| 4722 | SDL_Rect buttonPos = button->getSize(); | |||
| 4723 | auto& glyph = buttonAndGlyph.glyph; | |||
| 4724 | glyph->disabled = true; | |||
| 4725 | ||||
| 4726 | if ( !inputs.getVirtualMouse(player.playernum)->draw_cursor && inputs.hasController(player.playernum) ) | |||
| 4727 | { | |||
| 4728 | button->setColor(makeColor(255, 255, 255, 255)); | |||
| 4729 | } | |||
| 4730 | else | |||
| 4731 | { | |||
| 4732 | button->setColor(makeColor(255, 255, 255, 255)); | |||
| 4733 | } | |||
| 4734 | ||||
| 4735 | if ( player.bUseCompactGUIHeight() || player.bUseCompactGUIWidth() ) | |||
| 4736 | { | |||
| 4737 | if ( player.inventoryUI.chestGUI.bOpen ) | |||
| 4738 | { | |||
| 4739 | if ( buttonAndGlyph.inputName == "UINavRightTrigger" ) | |||
| 4740 | { | |||
| 4741 | button->setInvisible(true); | |||
| 4742 | continue; | |||
| 4743 | } | |||
| 4744 | } | |||
| 4745 | if ( player.shopGUI.bOpen ) | |||
| 4746 | { | |||
| 4747 | if ( buttonAndGlyph.inputName == "UINavRightTrigger" | |||
| 4748 | || (inputs.getVirtualMouse(player.playernum)->draw_cursor && player.bUseCompactGUIWidth()) ) | |||
| 4749 | { | |||
| 4750 | button->setInvisible(true); | |||
| 4751 | continue; | |||
| 4752 | } | |||
| 4753 | } | |||
| 4754 | if ( GenericGUI[player.playernum].isGUIOpen() || player.GUI.isDropdownActive() | |||
| 4755 | || player.minimap.mapWindow || player.messageZone.logWindow || player.hud.statusFxFocusedWindowActive ) | |||
| 4756 | { | |||
| 4757 | button->setDisabled(true); | |||
| 4758 | continue; | |||
| 4759 | } | |||
| 4760 | } | |||
| 4761 | ||||
| 4762 | if ( buttonAndGlyph.name == "magic button" || buttonAndGlyph.name == "items button" ) | |||
| 4763 | { | |||
| 4764 | if ( inputs.bPlayerUsingKeyboardControl(player.playernum) | |||
| 4765 | && inputs.getVirtualMouse(player.playernum)->draw_cursor | |||
| 4766 | && (!player.bUseCompactGUIHeight() && !player.bUseCompactGUIWidth()) | |||
| 4767 | && !GenericGUI[player.playernum].isGUIOpen() | |||
| 4768 | && !player.minimap.mapWindow | |||
| 4769 | && !player.messageZone.logWindow | |||
| 4770 | && !player.hud.statusFxFocusedWindowActive ) | |||
| 4771 | { | |||
| 4772 | if ( player.inventory_mode == INVENTORY_MODE_ITEM ) | |||
| 4773 | { | |||
| 4774 | if ( buttonAndGlyph.name == "magic button" ) | |||
| 4775 | { | |||
| 4776 | button->setDisabled(false); | |||
| 4777 | glyph->disabled = false; | |||
| 4778 | ||||
| 4779 | buttonPos.x = leftAnchorX; | |||
| 4780 | buttonPos.y = 8; | |||
| 4781 | buttonAndGlyph.inputName = "Spell List"; | |||
| 4782 | } | |||
| 4783 | } | |||
| 4784 | else if ( player.inventory_mode == INVENTORY_MODE_SPELL ) | |||
| 4785 | { | |||
| 4786 | if ( buttonAndGlyph.name == "items button" ) | |||
| 4787 | { | |||
| 4788 | button->setDisabled(false); | |||
| 4789 | glyph->disabled = false; | |||
| 4790 | ||||
| 4791 | buttonPos.x = leftAnchorX; | |||
| 4792 | buttonPos.y = 8; | |||
| 4793 | buttonAndGlyph.inputName = "Spell List"; | |||
| 4794 | } | |||
| 4795 | } | |||
| 4796 | } | |||
| 4797 | else if ( player.bUseCompactGUIHeight() || player.bUseCompactGUIWidth() ) | |||
| 4798 | { | |||
| 4799 | if ( !player.bUseCompactGUIWidth() ) | |||
| 4800 | { | |||
| 4801 | // align next to inventory | |||
| 4802 | buttonPos.x = leftAnchorX; | |||
| 4803 | } | |||
| 4804 | else | |||
| 4805 | { | |||
| 4806 | buttonPos.x = leftAlignX; | |||
| 4807 | } | |||
| 4808 | if ( numButtonsToShow < 4 ) | |||
| 4809 | { | |||
| 4810 | buttonPos.y = topAlignY; | |||
| 4811 | if ( !player.bUseCompactGUIWidth() ) | |||
| 4812 | { | |||
| 4813 | if ( players[player.playernum]->hud.xpFrame ) | |||
| 4814 | { | |||
| 4815 | SDL_Rect xpFramePos = players[player.playernum]->hud.xpFrame->getSize(); | |||
| 4816 | buttonPos.y = xpFramePos.y + 8; | |||
| 4817 | } | |||
| 4818 | } | |||
| 4819 | ||||
| 4820 | if ( compactLayoutMode == COMPACT_LAYOUT_INVENTORY ) | |||
| 4821 | { | |||
| 4822 | if ( buttonAndGlyph.name == "items button" && player.inventory_mode == INVENTORY_MODE_ITEM ) | |||
| 4823 | { | |||
| 4824 | // leave disabled | |||
| 4825 | button->setDisabled(true); | |||
| 4826 | glyph->disabled = true; | |||
| 4827 | } | |||
| 4828 | else if ( buttonAndGlyph.name == "magic button" && player.inventory_mode == INVENTORY_MODE_SPELL ) | |||
| 4829 | { | |||
| 4830 | // leave disabled | |||
| 4831 | button->setDisabled(true); | |||
| 4832 | glyph->disabled = true; | |||
| 4833 | } | |||
| 4834 | else | |||
| 4835 | { | |||
| 4836 | button->setDisabled(false); | |||
| 4837 | glyph->disabled = false; | |||
| 4838 | } | |||
| 4839 | } | |||
| 4840 | else if ( buttonAndGlyph.layoutMode == compactLayoutMode ) | |||
| 4841 | { | |||
| 4842 | button->setDisabled(false); | |||
| 4843 | glyph->disabled = false; | |||
| 4844 | } | |||
| 4845 | } | |||
| 4846 | else | |||
| 4847 | { | |||
| 4848 | button->setDisabled(false); | |||
| 4849 | glyph->disabled = false; | |||
| 4850 | if ( buttonAndGlyph.name == "magic button" ) | |||
| 4851 | { | |||
| 4852 | buttonPos.y = topAlignY; | |||
| 4853 | } | |||
| 4854 | else if ( buttonAndGlyph.name == "items button" ) | |||
| 4855 | { | |||
| 4856 | buttonPos.y = bottomAlignY; | |||
| 4857 | } | |||
| 4858 | } | |||
| 4859 | } | |||
| 4860 | buttonPos.w = buttonWidth; | |||
| 4861 | buttonPos.h = buttonHeight; | |||
| 4862 | button->setSize(buttonPos); | |||
| 4863 | } | |||
| 4864 | if ( buttonAndGlyph.name == "status button" || buttonAndGlyph.name == "skills button" ) | |||
| 4865 | { | |||
| 4866 | if ( inputs.bPlayerUsingKeyboardControl(player.playernum) | |||
| 4867 | && inputs.getVirtualMouse(player.playernum)->draw_cursor | |||
| 4868 | && (!player.bUseCompactGUIHeight() && !player.bUseCompactGUIWidth()) ) | |||
| 4869 | { | |||
| 4870 | // leave disabled | |||
| 4871 | } | |||
| 4872 | else if ( player.bUseCompactGUIHeight() || player.bUseCompactGUIWidth() ) | |||
| 4873 | { | |||
| 4874 | if ( !player.bUseCompactGUIWidth() ) | |||
| 4875 | { | |||
| 4876 | // align next to right panel | |||
| 4877 | buttonPos.x = rightAnchorX - buttonPos.w; | |||
| 4878 | } | |||
| 4879 | else | |||
| 4880 | { | |||
| 4881 | buttonPos.x = rightAlignX; | |||
| 4882 | } | |||
| 4883 | if ( numButtonsToShow < 4 ) | |||
| 4884 | { | |||
| 4885 | buttonPos.y = topAlignY; | |||
| 4886 | if ( !player.bUseCompactGUIWidth() ) | |||
| 4887 | { | |||
| 4888 | if ( players[player.playernum]->hud.xpFrame ) | |||
| 4889 | { | |||
| 4890 | SDL_Rect xpFramePos = players[player.playernum]->hud.xpFrame->getSize(); | |||
| 4891 | buttonPos.y = xpFramePos.y + 8; | |||
| 4892 | } | |||
| 4893 | } | |||
| 4894 | if ( buttonAndGlyph.layoutMode == compactLayoutMode ) | |||
| 4895 | { | |||
| 4896 | button->setDisabled(false); | |||
| 4897 | glyph->disabled = false; | |||
| 4898 | } | |||
| 4899 | } | |||
| 4900 | else | |||
| 4901 | { | |||
| 4902 | button->setDisabled(false); | |||
| 4903 | glyph->disabled = false; | |||
| 4904 | if ( buttonAndGlyph.name == "status button" ) | |||
| 4905 | { | |||
| 4906 | buttonPos.y = topAlignY; | |||
| 4907 | } | |||
| 4908 | else if ( buttonAndGlyph.name == "skills button" ) | |||
| 4909 | { | |||
| 4910 | buttonPos.y = bottomAlignY; | |||
| 4911 | } | |||
| 4912 | } | |||
| 4913 | } | |||
| 4914 | buttonPos.w = buttonWidth; | |||
| 4915 | buttonPos.h = buttonHeight; | |||
| 4916 | button->setSize(buttonPos); | |||
| 4917 | } | |||
| 4918 | ||||
| 4919 | if ( !button->isDisabled() ) | |||
| 4920 | { | |||
| 4921 | glyph->path = Input::inputs[player.playernum].getGlyphPathForBinding(buttonAndGlyph.inputName.c_str()); | |||
| 4922 | glyph->ontop = true; | |||
| 4923 | if ( inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 4924 | { | |||
| 4925 | glyph->disabled = false; | |||
| 4926 | } | |||
| 4927 | else | |||
| 4928 | { | |||
| 4929 | glyph->disabled = false; | |||
| 4930 | } | |||
| 4931 | if ( auto imgGet = Image::get(glyph->path.c_str()) ) | |||
| 4932 | { | |||
| 4933 | glyph->pos.w = (int)imgGet->getWidth(); | |||
| 4934 | glyph->pos.h = (int)imgGet->getHeight(); | |||
| 4935 | } | |||
| 4936 | ||||
| 4937 | glyph->pos.x = button->getSize().x + button->getSize().w / 2 - glyph->pos.w / 2; // center the x for the glyph | |||
| 4938 | const int glyphToImgPadY = 8; | |||
| 4939 | glyph->pos.y = button->getSize().y + button->getSize().h - glyphToImgPadY; // just below the button with some padding | |||
| 4940 | } | |||
| 4941 | button->setInvisible(button->isDisabled()); | |||
| 4942 | } | |||
| 4943 | ||||
| 4944 | for ( auto& buttonAndGlyph : allButtonsAndGlyphs ) | |||
| 4945 | { | |||
| 4946 | auto& button = buttonAndGlyph.button; | |||
| 4947 | if ( !button->isDisabled() && !button->isInvisible() ) | |||
| 4948 | { | |||
| 4949 | if ( player.GUI.bModuleAccessibleWithMouse(Player::GUI_t::MODULE_INVENTORY) | |||
| 4950 | && inputs.getVirtualMouse(player.playernum)->draw_cursor | |||
| 4951 | && button->isHighlighted() ) | |||
| 4952 | { | |||
| 4953 | player.GUI.setHoveringOverModuleButton(Player::GUI_t::MODULE_INVENTORY); | |||
| 4954 | SDL_Rect pos = button->getAbsoluteSize(); | |||
| 4955 | // make sure to adjust absolute size to camera viewport | |||
| 4956 | pos.x -= player.camera_virtualx1(); | |||
| 4957 | pos.y -= player.camera_virtualy1(); | |||
| 4958 | player.hud.setCursorDisabled(false); | |||
| 4959 | player.hud.updateCursorAnimation(pos.x - 1, pos.y - 1, pos.w, pos.h, inputs.getVirtualMouse(player.playernum)->draw_cursor); | |||
| 4960 | } | |||
| 4961 | ||||
| 4962 | if ( buttonAndGlyph.inputName == "UINavLeftTrigger" && leftTriggerPressed | |||
| 4963 | && player.GUI.bModuleAccessibleWithMouse(Player::GUI_t::MODULE_INVENTORY) ) | |||
| 4964 | { | |||
| 4965 | leftTriggerPressed = false; | |||
| 4966 | button->activate(); | |||
| 4967 | } | |||
| 4968 | else if ( buttonAndGlyph.inputName == "UINavRightTrigger" && rightTriggerPressed | |||
| 4969 | && player.GUI.bModuleAccessibleWithMouse(Player::GUI_t::MODULE_INVENTORY) ) | |||
| 4970 | { | |||
| 4971 | rightTriggerPressed = false; | |||
| 4972 | button->activate(); | |||
| 4973 | } | |||
| 4974 | } | |||
| 4975 | } | |||
| 4976 | } | |||
| 4977 | ||||
| 4978 | bool StatusEffectQueue_t::insertEffect(int effectID, int spellID) | |||
| 4979 | { | |||
| 4980 | if ( spellID >= 0 && spellID < NUM_SPELLS ) | |||
| 4981 | { | |||
| 4982 | effectID = spellID + kSpellEffectOffset; | |||
| 4983 | if ( StatusEffectDefinitions_t::sustainedSpellDefinitionExists(effectID) ) | |||
| 4984 | { | |||
| 4985 | if ( StatusEffectDefinitions_t::getSustainedSpell(effectID).neverDisplay ) | |||
| 4986 | { | |||
| 4987 | return false; | |||
| 4988 | } | |||
| 4989 | } | |||
| 4990 | } | |||
| 4991 | if ( (effectID >= 0 && effectID < NUMEFFECTS) | |||
| 4992 | || effectID == kEffectBread | |||
| 4993 | || effectID == kEffectBloodHunger | |||
| 4994 | || effectID == kEffectAutomatonHunger | |||
| 4995 | || effectID >= kSpellEffectOffset ) | |||
| 4996 | { | |||
| 4997 | if ( StatusEffectDefinitions_t::effectDefinitionExists(effectID) ) | |||
| 4998 | { | |||
| 4999 | if ( StatusEffectDefinitions_t::getEffect(effectID).neverDisplay ) | |||
| 5000 | { | |||
| 5001 | return false; | |||
| 5002 | } | |||
| 5003 | } | |||
| 5004 | for ( auto& q : effectQueue ) | |||
| 5005 | { | |||
| 5006 | if ( effectID == q.effect ) | |||
| 5007 | { | |||
| 5008 | return false; | |||
| 5009 | } | |||
| 5010 | } | |||
| 5011 | } | |||
| 5012 | ||||
| 5013 | effectQueue.push_back(StatusEffectQueueEntry_t(effectID)); | |||
| 5014 | effectQueue.back().pos.x = getBaseEffectPosX(); | |||
| 5015 | effectQueue.back().pos.y = getBaseEffectPosY(); | |||
| 5016 | notificationQueue.push_back(StatusEffectQueueEntry_t(effectID)); | |||
| 5017 | notificationQueue.back().pos.x = getBaseEffectPosX(); | |||
| 5018 | notificationQueue.back().pos.y = getBaseEffectPosY(); | |||
| 5019 | ||||
| 5020 | // fall back if notificationTargetPosition doesn't have an effect to go to. | |||
| 5021 | notificationQueue.back().notificationTargetPosition.x = 0; | |||
| 5022 | notificationQueue.back().notificationTargetPosition.y = statusEffectFrame->getSize().h - notificationQueue.back().notificationTargetPosition.h; | |||
| 5023 | requiresAnimUpdate = true; | |||
| 5024 | return true; | |||
| 5025 | } | |||
| 5026 | ||||
| 5027 | std::string StatusEffectQueue_t::StatusEffectDefinitions_t::getEffectImgPath(StatusEffectQueue_t::EffectDefinitionEntry_t& entry, int variation) | |||
| 5028 | { | |||
| 5029 | if ( entry.imgPath == "" ) | |||
| 5030 | { | |||
| 5031 | if ( entry.imgPathVariations.size() > 0 && variation >= 0 ) | |||
| 5032 | { | |||
| 5033 | return entry.imgPathVariations[std::min(variation, (int)entry.imgPathVariations.size() - 1)]; | |||
| 5034 | } | |||
| 5035 | node_t* spellImageNode = nullptr; | |||
| 5036 | int spellID = entry.useSpellIDForImg; | |||
| 5037 | if ( variation >= 0 ) | |||
| 5038 | { | |||
| 5039 | spellID = entry.useSpellIDForImgVariations[std::min(variation, (int)entry.useSpellIDForImgVariations.size() - 1)]; | |||
| 5040 | } | |||
| 5041 | if ( spellID >= 0 && spellID < NUM_SPELLS ) | |||
| 5042 | { | |||
| 5043 | spellImageNode = ItemTooltips.getSpellNodeFromSpellID(spellID); | |||
| 5044 | } | |||
| 5045 | if ( spellImageNode ) | |||
| 5046 | { | |||
| 5047 | string_t* string = (string_t*)spellImageNode->element; | |||
| 5048 | if ( string ) | |||
| 5049 | { | |||
| 5050 | return string->data; | |||
| 5051 | } | |||
| 5052 | } | |||
| 5053 | return "images/sprites/null.png"; | |||
| 5054 | } | |||
| 5055 | if ( entry.imgPath == "" ) | |||
| 5056 | { | |||
| 5057 | return "images/sprites/null.png"; | |||
| 5058 | } | |||
| 5059 | return entry.imgPath; | |||
| 5060 | } | |||
| 5061 | ||||
| 5062 | void StatusEffectQueueEntry_t::setAnimatePosition(int destx, int desty, int destw, int desth) | |||
| 5063 | { | |||
| 5064 | animateStartX = pos.x; | |||
| 5065 | animateStartY = pos.y; | |||
| 5066 | animateStartW = pos.w; | |||
| 5067 | animateStartH = pos.h; | |||
| 5068 | animateSetpointX = destx; | |||
| 5069 | animateSetpointY = desty; | |||
| 5070 | animateSetpointW = destw; | |||
| 5071 | animateSetpointH = desth; | |||
| 5072 | animateX = 0.0; | |||
| 5073 | animateY = 0.0; | |||
| 5074 | animateW = 0.0; | |||
| 5075 | animateH = 0.0; | |||
| 5076 | } | |||
| 5077 | ||||
| 5078 | void StatusEffectQueueEntry_t::setAnimatePosition(int destx, int desty) | |||
| 5079 | { | |||
| 5080 | animateStartX = pos.x; | |||
| 5081 | animateStartY = pos.y; | |||
| 5082 | animateStartW = pos.w; | |||
| 5083 | animateStartH = pos.h; | |||
| 5084 | animateSetpointX = destx; | |||
| 5085 | animateSetpointY = desty; | |||
| 5086 | animateSetpointW = 0; | |||
| 5087 | animateSetpointH = 0; | |||
| 5088 | animateX = 0.0; | |||
| 5089 | animateY = 0.0; | |||
| 5090 | animateW = 0.0; | |||
| 5091 | animateH = 0.0; | |||
| 5092 | } | |||
| 5093 | ||||
| 5094 | const real_t kStatusEffectQueueAnimSpeedMult = 4.0; | |||
| 5095 | ||||
| 5096 | void StatusEffectQueueEntry_t::animate() | |||
| 5097 | { | |||
| 5098 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 5099 | real_t setpointDiffX = fpsScale * std::max(.1, (1.0 - animateX)) / (5.0 / kStatusEffectQueueAnimSpeedMult); | |||
| 5100 | real_t setpointDiffY = fpsScale * std::max(.1, (1.0 - animateY)) / (5.0 / kStatusEffectQueueAnimSpeedMult); | |||
| 5101 | animateX += setpointDiffX; | |||
| 5102 | animateY += setpointDiffY; | |||
| 5103 | animateX = std::min(1.0, animateX); | |||
| 5104 | animateY = std::min(1.0, animateY); | |||
| 5105 | ||||
| 5106 | int destX = animateSetpointX - animateStartX; | |||
| 5107 | int destY = animateSetpointY - animateStartY; | |||
| 5108 | ||||
| 5109 | pos.x = animateStartX + destX * animateX; | |||
| 5110 | pos.y = animateStartY + destY * animateY; | |||
| 5111 | } | |||
| 5112 | ||||
| 5113 | void StatusEffectQueue_t::loadStatusEffectsJSON() | |||
| 5114 | { | |||
| 5115 | if ( !PHYSFS_getRealDir("/data/status_effects.json") ) | |||
| 5116 | { | |||
| 5117 | printlog("[JSON]: Error: Could not find file: data/status_effects.json"); | |||
| 5118 | } | |||
| 5119 | else | |||
| 5120 | { | |||
| 5121 | std::string inputPath = PHYSFS_getRealDir("/data/status_effects.json"); | |||
| 5122 | inputPath.append("/data/status_effects.json"); | |||
| 5123 | ||||
| 5124 | File* fp = FileIO::open(inputPath.c_str(), "rb"); | |||
| 5125 | if ( !fp ) | |||
| 5126 | { | |||
| 5127 | printlog("[JSON]: Error: Could not open json file %s", inputPath.c_str()); | |||
| 5128 | } | |||
| 5129 | else | |||
| 5130 | { | |||
| 5131 | char buf[65536]; | |||
| 5132 | int count = fp->read(buf, sizeof(buf[0]), sizeof(buf)); | |||
| 5133 | buf[count] = '\0'; | |||
| 5134 | rapidjson::StringStream is(buf); | |||
| 5135 | FileIO::close(fp); | |||
| 5136 | ||||
| 5137 | rapidjson::Document d; | |||
| 5138 | d.ParseStream(is); | |||
| 5139 | if ( !d.HasMember("version") ) | |||
| 5140 | { | |||
| 5141 | printlog("[JSON]: Error: No 'version' value in json file, or JSON syntax incorrect! %s", inputPath.c_str()); | |||
| 5142 | } | |||
| 5143 | else | |||
| 5144 | { | |||
| 5145 | StatusEffectDefinitions_t::reset(); | |||
| 5146 | int defaultTooltipWidth = 200; | |||
| 5147 | if ( d.HasMember("default_tooltip_width") ) | |||
| 5148 | { | |||
| 5149 | defaultTooltipWidth = d["default_tooltip_width"].GetInt(); | |||
| 5150 | } | |||
| 5151 | if ( d.HasMember("colors") ) | |||
| 5152 | { | |||
| 5153 | if ( d["colors"].HasMember("notification_text") ) | |||
| 5154 | { | |||
| 5155 | StatusEffectDefinitions_t::notificationTextColor = makeColor( | |||
| 5156 | d["colors"]["notification_text"]["r"].GetInt(), | |||
| 5157 | d["colors"]["notification_text"]["g"].GetInt(), | |||
| 5158 | d["colors"]["notification_text"]["b"].GetInt(), | |||
| 5159 | d["colors"]["notification_text"]["a"].GetInt()); | |||
| 5160 | } | |||
| 5161 | if ( d["colors"].HasMember("tooltip_desc_text") ) | |||
| 5162 | { | |||
| 5163 | StatusEffectDefinitions_t::tooltipDescColor = makeColor( | |||
| 5164 | d["colors"]["tooltip_desc_text"]["r"].GetInt(), | |||
| 5165 | d["colors"]["tooltip_desc_text"]["g"].GetInt(), | |||
| 5166 | d["colors"]["tooltip_desc_text"]["b"].GetInt(), | |||
| 5167 | d["colors"]["tooltip_desc_text"]["a"].GetInt()); | |||
| 5168 | } | |||
| 5169 | if ( d["colors"].HasMember("tooltip_heading_text") ) | |||
| 5170 | { | |||
| 5171 | StatusEffectDefinitions_t::tooltipHeadingColor = makeColor( | |||
| 5172 | d["colors"]["tooltip_heading_text"]["r"].GetInt(), | |||
| 5173 | d["colors"]["tooltip_heading_text"]["g"].GetInt(), | |||
| 5174 | d["colors"]["tooltip_heading_text"]["b"].GetInt(), | |||
| 5175 | d["colors"]["tooltip_heading_text"]["a"].GetInt()); | |||
| 5176 | } | |||
| 5177 | } | |||
| 5178 | if ( d.HasMember("notification_font") ) | |||
| 5179 | { | |||
| 5180 | StatusEffectDefinitions_t::notificationFont = d["notification_font"].GetString(); | |||
| 5181 | } | |||
| 5182 | if ( d.HasMember("sustained_effects") ) | |||
| 5183 | { | |||
| 5184 | for ( rapidjson::Value::ConstMemberIterator itr = d["sustained_effects"].MemberBegin(); | |||
| 5185 | itr != d["sustained_effects"].MemberEnd(); ++itr ) | |||
| 5186 | { | |||
| 5187 | int id = -1; | |||
| 5188 | if ( itr->value.HasMember("id") ) | |||
| 5189 | { | |||
| 5190 | id = itr->value["id"].GetInt(); | |||
| 5191 | } | |||
| 5192 | int spellID = -1; | |||
| 5193 | if ( itr->value.HasMember("spell_id") ) | |||
| 5194 | { | |||
| 5195 | spellID = itr->value["spell_id"].GetInt(); | |||
| 5196 | } | |||
| 5197 | StatusEffectDefinitions_t::allSustainedSpells.insert( | |||
| 5198 | std::make_pair(spellID, EffectDefinitionEntry_t())); | |||
| 5199 | auto& entry = StatusEffectDefinitions_t::allSustainedSpells[spellID]; | |||
| 5200 | entry.effect_id = id; | |||
| 5201 | entry.spell_id = spellID; | |||
| 5202 | entry.internal_name = itr->name.GetString(); | |||
| 5203 | if ( itr->value["name"].IsArray() ) | |||
| 5204 | { | |||
| 5205 | for ( auto arr = itr->value["name"].Begin(); | |||
| 5206 | arr != itr->value["name"].End(); ++arr ) | |||
| 5207 | { | |||
| 5208 | entry.nameVariations.push_back(arr->GetString()); | |||
| 5209 | } | |||
| 5210 | } | |||
| 5211 | else | |||
| 5212 | { | |||
| 5213 | entry.name = itr->value["name"].GetString(); | |||
| 5214 | } | |||
| 5215 | std::string buf = itr->value["desc"].GetString(); | |||
| 5216 | entry.desc = "\x1E "; | |||
| 5217 | int index = 0; | |||
| 5218 | for ( auto s : buf ) | |||
| 5219 | { | |||
| 5220 | if ( index == 0 && (buf[0] == '+' || buf[0] == '-') ) | |||
| 5221 | { | |||
| 5222 | entry.desc = ""; | |||
| 5223 | } | |||
| 5224 | entry.desc += s; | |||
| 5225 | if ( s == '\n' ) | |||
| 5226 | { | |||
| 5227 | if ( index + 1 < buf.size() ) | |||
| 5228 | { | |||
| 5229 | if ( buf[index + 1] == '+' || buf[index + 1] == '-' ) | |||
| 5230 | { | |||
| 5231 | // skip adding dot | |||
| 5232 | ++index; | |||
| 5233 | continue; | |||
| 5234 | } | |||
| 5235 | } | |||
| 5236 | entry.desc += "\x1E "; | |||
| 5237 | } | |||
| 5238 | ++index; | |||
| 5239 | } | |||
| 5240 | entry.imgPath = itr->value["img_path"].GetString(); | |||
| 5241 | entry.useSpellIDForImg = itr->value["img_from_spell_id"].GetInt(); | |||
| 5242 | entry.neverDisplay = false; | |||
| 5243 | if ( itr->value.HasMember("never_display") ) | |||
| 5244 | { | |||
| 5245 | entry.neverDisplay = itr->value["never_display"].GetBool(); | |||
| 5246 | } | |||
| 5247 | entry.tooltipWidth = defaultTooltipWidth; | |||
| 5248 | if ( itr->value.HasMember("tooltip_width") ) | |||
| 5249 | { | |||
| 5250 | entry.tooltipWidth = itr->value["tooltip_width"].GetInt(); | |||
| 5251 | } | |||
| 5252 | } | |||
| 5253 | } | |||
| 5254 | if ( d.HasMember("effects") ) | |||
| 5255 | { | |||
| 5256 | for ( rapidjson::Value::ConstMemberIterator itr = d["effects"].MemberBegin(); | |||
| 5257 | itr != d["effects"].MemberEnd(); ++itr ) | |||
| 5258 | { | |||
| 5259 | int id = -1; | |||
| 5260 | if ( itr->value.HasMember("id") ) | |||
| 5261 | { | |||
| 5262 | id = itr->value["id"].GetInt(); | |||
| 5263 | } | |||
| 5264 | StatusEffectDefinitions_t::allEffects.insert( | |||
| 5265 | std::make_pair(id, EffectDefinitionEntry_t())); | |||
| 5266 | auto& entry = StatusEffectDefinitions_t::allEffects[id]; | |||
| 5267 | entry.effect_id = id; | |||
| 5268 | if ( itr->value["name"].IsArray() ) | |||
| 5269 | { | |||
| 5270 | for ( auto arr = itr->value["name"].Begin(); | |||
| 5271 | arr != itr->value["name"].End(); ++arr ) | |||
| 5272 | { | |||
| 5273 | entry.nameVariations.push_back(arr->GetString()); | |||
| 5274 | } | |||
| 5275 | } | |||
| 5276 | else | |||
| 5277 | { | |||
| 5278 | entry.name = itr->value["name"].GetString(); | |||
| 5279 | } | |||
| 5280 | if ( itr->value["desc"].IsArray() ) | |||
| 5281 | { | |||
| 5282 | for ( auto arr = itr->value["desc"].Begin(); | |||
| 5283 | arr != itr->value["desc"].End(); ++arr ) | |||
| 5284 | { | |||
| 5285 | std::string buf = arr->GetString(); | |||
| 5286 | int index = 0; | |||
| 5287 | std::string formattedStr = "\x1E "; | |||
| 5288 | for ( auto s : buf ) | |||
| 5289 | { | |||
| 5290 | if ( index == 0 && (buf[0] == '+' || buf[0] == '-') ) | |||
| 5291 | { | |||
| 5292 | formattedStr = ""; | |||
| 5293 | } | |||
| 5294 | formattedStr += s; | |||
| 5295 | if ( s == '\n' ) | |||
| 5296 | { | |||
| 5297 | if ( index + 1 < buf.size() ) | |||
| 5298 | { | |||
| 5299 | if ( buf[index + 1] == '+' || buf[index + 1] == '-' ) | |||
| 5300 | { | |||
| 5301 | // skip adding dot | |||
| 5302 | ++index; | |||
| 5303 | continue; | |||
| 5304 | } | |||
| 5305 | } | |||
| 5306 | formattedStr += "\x1E "; | |||
| 5307 | } | |||
| 5308 | ++index; | |||
| 5309 | } | |||
| 5310 | entry.descVariations.push_back(formattedStr); | |||
| 5311 | } | |||
| 5312 | } | |||
| 5313 | else | |||
| 5314 | { | |||
| 5315 | std::string buf = itr->value["desc"].GetString(); | |||
| 5316 | entry.desc = "\x1E "; | |||
| 5317 | int index = 0; | |||
| 5318 | for ( auto s : buf ) | |||
| 5319 | { | |||
| 5320 | if ( index == 0 && (buf[0] == '+' || buf[0] == '-') ) | |||
| 5321 | { | |||
| 5322 | entry.desc = ""; | |||
| 5323 | } | |||
| 5324 | entry.desc += s; | |||
| 5325 | if ( s == '\n' ) | |||
| 5326 | { | |||
| 5327 | if ( index + 1 < buf.size() ) | |||
| 5328 | { | |||
| 5329 | if ( buf[index + 1] == '+' || buf[index + 1] == '-' ) | |||
| 5330 | { | |||
| 5331 | // skip adding dot | |||
| 5332 | ++index; | |||
| 5333 | continue; | |||
| 5334 | } | |||
| 5335 | } | |||
| 5336 | entry.desc += "\x1E "; | |||
| 5337 | } | |||
| 5338 | ++index; | |||
| 5339 | } | |||
| 5340 | } | |||
| 5341 | entry.internal_name = itr->name.GetString(); | |||
| 5342 | if ( itr->value["img_path"].IsArray() ) | |||
| 5343 | { | |||
| 5344 | for ( auto arr = itr->value["img_path"].Begin(); | |||
| 5345 | arr != itr->value["img_path"].End(); ++arr ) | |||
| 5346 | { | |||
| 5347 | entry.imgPathVariations.push_back(arr->GetString()); | |||
| 5348 | } | |||
| 5349 | } | |||
| 5350 | else | |||
| 5351 | { | |||
| 5352 | entry.imgPath = itr->value["img_path"].GetString(); | |||
| 5353 | } | |||
| 5354 | if ( itr->value["img_from_spell_id"].IsArray() ) | |||
| 5355 | { | |||
| 5356 | for ( auto arr = itr->value["img_from_spell_id"].Begin(); | |||
| 5357 | arr != itr->value["img_from_spell_id"].End(); ++arr ) | |||
| 5358 | { | |||
| 5359 | entry.useSpellIDForImgVariations.push_back(arr->GetInt()); | |||
| 5360 | } | |||
| 5361 | } | |||
| 5362 | else | |||
| 5363 | { | |||
| 5364 | entry.useSpellIDForImg = itr->value["img_from_spell_id"].GetInt(); | |||
| 5365 | } | |||
| 5366 | entry.sustainedSpellID = -1; | |||
| 5367 | if ( itr->value.HasMember("use_entry_for_sustained_spell") ) | |||
| 5368 | { | |||
| 5369 | entry.sustainedSpellID = itr->value["use_entry_for_sustained_spell"].GetInt(); | |||
| 5370 | } | |||
| 5371 | entry.neverDisplay = false; | |||
| 5372 | if ( itr->value.HasMember("never_display") ) | |||
| 5373 | { | |||
| 5374 | entry.neverDisplay = itr->value["never_display"].GetBool(); | |||
| 5375 | } | |||
| 5376 | entry.tooltipWidth = defaultTooltipWidth; | |||
| 5377 | if ( itr->value.HasMember("tooltip_width") ) | |||
| 5378 | { | |||
| 5379 | entry.tooltipWidth = itr->value["tooltip_width"].GetInt(); | |||
| 5380 | } | |||
| 5381 | } | |||
| 5382 | } | |||
| 5383 | printlog("[JSON]: Successfully read json file %s", inputPath.c_str()); | |||
| 5384 | } | |||
| 5385 | } | |||
| 5386 | } | |||
| 5387 | } | |||
| 5388 | ||||
| 5389 | int StatusEffectQueue_t::getBaseEffectPosX() | |||
| 5390 | { | |||
| 5391 | if ( players[player]->bUseCompactGUIHeight() ) | |||
| 5392 | { | |||
| 5393 | return statusEffectFrame->getSize().w / 2 - 100; | |||
| 5394 | } | |||
| 5395 | return statusEffectFrame->getSize().w / 2 - 100; | |||
| 5396 | } | |||
| 5397 | int StatusEffectQueue_t::getBaseEffectPosY() | |||
| 5398 | { | |||
| 5399 | if ( players[player]->bUseCompactGUIHeight() ) | |||
| 5400 | { | |||
| 5401 | if ( players[player]->bUseCompactGUIWidth() && !players[player]->hotbar.useHotbarFaceMenu ) | |||
| 5402 | { | |||
| 5403 | return statusEffectFrame->getSize().h / 2 + 32; | |||
| 5404 | } | |||
| 5405 | return statusEffectFrame->getSize().h / 2; | |||
| 5406 | } | |||
| 5407 | return statusEffectFrame->getSize().h / 2 - 50; | |||
| 5408 | } | |||
| 5409 | ||||
| 5410 | int StatusEffectQueueEntry_t::getEffectSpriteNormalWidth() | |||
| 5411 | { | |||
| 5412 | if ( effect == StatusEffectQueue_t::kEffectBread | |||
| 5413 | || effect == StatusEffectQueue_t::kEffectBloodHunger ) | |||
| 5414 | { | |||
| 5415 | return 76; | |||
| 5416 | } | |||
| 5417 | else if ( effect == StatusEffectQueue_t::kEffectAutomatonHunger ) | |||
| 5418 | { | |||
| 5419 | return 64; | |||
| 5420 | } | |||
| 5421 | return 32; | |||
| 5422 | } | |||
| 5423 | int StatusEffectQueueEntry_t::getEffectSpriteNormalHeight() | |||
| 5424 | { | |||
| 5425 | if ( effect == StatusEffectQueue_t::kEffectBread | |||
| 5426 | || effect == StatusEffectQueue_t::kEffectBloodHunger ) | |||
| 5427 | { | |||
| 5428 | return 60; | |||
| 5429 | } | |||
| 5430 | else if ( effect == StatusEffectQueue_t::kEffectAutomatonHunger ) | |||
| 5431 | { | |||
| 5432 | return 64; | |||
| 5433 | } | |||
| 5434 | return 32; | |||
| 5435 | } | |||
| 5436 | ||||
| 5437 | int getStatusEffectMovementAmount(int player) | |||
| 5438 | { | |||
| 5439 | int movementAmount = 50; | |||
| 5440 | if ( players[player]->bUseCompactGUIHeight() ) | |||
| 5441 | { | |||
| 5442 | movementAmount = 25; | |||
| 5443 | } | |||
| 5444 | return movementAmount; | |||
| 5445 | } | |||
| 5446 | ||||
| 5447 | real_t StatusEffectQueueEntry_t::getStatusEffectLargestScaling(int player) | |||
| 5448 | { | |||
| 5449 | if ( effect == StatusEffectQueue_t::kEffectBread | |||
| 5450 | || effect == StatusEffectQueue_t::kEffectBloodHunger | |||
| 5451 | || effect == StatusEffectQueue_t::kEffectAutomatonHunger ) | |||
| 5452 | { | |||
| 5453 | return 2.0; | |||
| 5454 | } | |||
| 5455 | return 3.0; | |||
| 5456 | } | |||
| 5457 | ||||
| 5458 | real_t StatusEffectQueueEntry_t::getStatusEffectMidScaling(int player) | |||
| 5459 | { | |||
| 5460 | if ( effect == StatusEffectQueue_t::kEffectBread | |||
| 5461 | || effect == StatusEffectQueue_t::kEffectBloodHunger | |||
| 5462 | || effect == StatusEffectQueue_t::kEffectAutomatonHunger ) | |||
| 5463 | { | |||
| 5464 | return 1.5; | |||
| 5465 | } | |||
| 5466 | return 2.0; | |||
| 5467 | } | |||
| 5468 | ||||
| 5469 | void StatusEffectQueueEntry_t::animateNotification(int player) | |||
| 5470 | { | |||
| 5471 | auto& statusEffectQueue = StatusEffectQueue[player]; | |||
| 5472 | real_t animspeed = 5.0 / kStatusEffectQueueAnimSpeedMult; | |||
| 5473 | const int movementAmount = getStatusEffectMovementAmount(player); | |||
| 5474 | switch ( notificationState ) | |||
| 5475 | { | |||
| 5476 | case STATE_1: | |||
| 5477 | if ( notificationStateInit == STATE_1 ) | |||
| 5478 | { | |||
| 5479 | notificationStateInit = STATE_2; | |||
| 5480 | setAnimatePosition( | |||
| 5481 | statusEffectQueue.getBaseEffectPosX() - movementAmount, | |||
| 5482 | statusEffectQueue.getBaseEffectPosY() - movementAmount, | |||
| 5483 | getEffectSpriteNormalWidth(), getEffectSpriteNormalHeight()); | |||
| 5484 | } | |||
| 5485 | if ( animateX >= 1.0 ) | |||
| 5486 | { | |||
| 5487 | notificationState = STATE_2; | |||
| 5488 | } | |||
| 5489 | animspeed *= 2.0; | |||
| 5490 | break; | |||
| 5491 | case STATE_2: | |||
| 5492 | if ( notificationStateInit == STATE_2 ) | |||
| 5493 | { | |||
| 5494 | notificationStateInit = STATE_3; | |||
| 5495 | setAnimatePosition( | |||
| 5496 | statusEffectQueue.getBaseEffectPosX() - movementAmount - (getStatusEffectLargestScaling(player) - 1.0) * getEffectSpriteNormalWidth() / 2, | |||
| 5497 | statusEffectQueue.getBaseEffectPosY() - movementAmount - (getStatusEffectLargestScaling(player) - 1.0) * getEffectSpriteNormalHeight() / 2, | |||
| 5498 | getEffectSpriteNormalWidth() * getStatusEffectLargestScaling(player), | |||
| 5499 | getEffectSpriteNormalHeight() * getStatusEffectLargestScaling(player)); | |||
| 5500 | } | |||
| 5501 | if ( animateX >= 1.0 ) | |||
| 5502 | { | |||
| 5503 | notificationState = STATE_3; | |||
| 5504 | } | |||
| 5505 | animspeed *= 4.0; | |||
| 5506 | break; | |||
| 5507 | case STATE_3: | |||
| 5508 | if ( notificationStateInit == STATE_3 ) | |||
| 5509 | { | |||
| 5510 | notificationStateInit = STATE_4; | |||
| 5511 | setAnimatePosition( | |||
| 5512 | statusEffectQueue.getBaseEffectPosX() - movementAmount - (getStatusEffectMidScaling(player) - 1.0) * getEffectSpriteNormalWidth() / 2, | |||
| 5513 | statusEffectQueue.getBaseEffectPosY() - movementAmount - (getStatusEffectMidScaling(player) - 1.0) * getEffectSpriteNormalHeight() / 2, | |||
| 5514 | getEffectSpriteNormalWidth() * getStatusEffectMidScaling(player), | |||
| 5515 | getEffectSpriteNormalHeight() * getStatusEffectMidScaling(player)); | |||
| 5516 | } | |||
| 5517 | if ( animateX >= 1.0 ) | |||
| 5518 | { | |||
| 5519 | notificationState = STATE_4; | |||
| 5520 | } | |||
| 5521 | animspeed *= 4.0; | |||
| 5522 | break; | |||
| 5523 | case STATE_4: | |||
| 5524 | if ( notificationStateInit == STATE_4 ) | |||
| 5525 | { | |||
| 5526 | notificationStateInit = STATE_END; | |||
| 5527 | setAnimatePosition(notificationTargetPosition.x, | |||
| 5528 | notificationTargetPosition.y, | |||
| 5529 | notificationTargetPosition.w, | |||
| 5530 | notificationTargetPosition.h); | |||
| 5531 | } | |||
| 5532 | if ( notificationTargetPosition.x != animateSetpointX | |||
| 5533 | || notificationTargetPosition.y != animateSetpointY | |||
| 5534 | || notificationTargetPosition.w != animateSetpointW | |||
| 5535 | || notificationTargetPosition.h != animateSetpointH ) | |||
| 5536 | { | |||
| 5537 | // re update this as our target moved. | |||
| 5538 | setAnimatePosition(notificationTargetPosition.x, | |||
| 5539 | notificationTargetPosition.y, | |||
| 5540 | notificationTargetPosition.w, | |||
| 5541 | notificationTargetPosition.h); | |||
| 5542 | } | |||
| 5543 | if ( animateX >= 1.0 ) | |||
| 5544 | { | |||
| 5545 | notificationState = STATE_END; | |||
| 5546 | } | |||
| 5547 | animspeed *= 2.0; | |||
| 5548 | break; | |||
| 5549 | case STATE_END: | |||
| 5550 | return; | |||
| 5551 | default: | |||
| 5552 | break; | |||
| 5553 | } | |||
| 5554 | ||||
| 5555 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 5556 | real_t setpointDiffX = fpsScale * std::max(.1, (1.0 - animateX)) / (animspeed); | |||
| 5557 | real_t setpointDiffY = fpsScale * std::max(.1, (1.0 - animateY)) / (animspeed); | |||
| 5558 | real_t setpointDiffW = fpsScale * std::max(.1, (1.0 - animateW)) / (animspeed); | |||
| 5559 | real_t setpointDiffH = fpsScale * std::max(.1, (1.0 - animateH)) / (animspeed); | |||
| 5560 | animateX += setpointDiffX; | |||
| 5561 | animateY += setpointDiffY; | |||
| 5562 | animateX = std::min(1.0, animateX); | |||
| 5563 | animateY = std::min(1.0, animateY); | |||
| 5564 | animateW += setpointDiffW; | |||
| 5565 | animateH += setpointDiffH; | |||
| 5566 | animateW = std::min(1.0, animateW); | |||
| 5567 | animateH = std::min(1.0, animateH); | |||
| 5568 | ||||
| 5569 | int destX = animateSetpointX - animateStartX; | |||
| 5570 | int destY = animateSetpointY - animateStartY; | |||
| 5571 | int destW = animateSetpointW - animateStartW; | |||
| 5572 | int destH = animateSetpointH - animateStartH; | |||
| 5573 | ||||
| 5574 | pos.x = animateStartX + destX * animateX; | |||
| 5575 | pos.y = animateStartY + destY * animateY; | |||
| 5576 | pos.w = animateStartW + destW * animateW; | |||
| 5577 | pos.h = animateStartH + destH * animateH; | |||
| 5578 | } | |||
| 5579 | ||||
| 5580 | void createStatusEffectQueue(const int player) | |||
| 5581 | { | |||
| 5582 | auto& statusEffectQueue = StatusEffectQueue[player]; | |||
| 5583 | if ( statusEffectQueue.statusEffectFrame ) | |||
| 5584 | { | |||
| 5585 | return; | |||
| 5586 | } | |||
| 5587 | auto& hud_t = players[player]->hud; | |||
| 5588 | statusEffectQueue.statusEffectFrame = hud_t.hudFrame->addFrame("status effects"); | |||
| 5589 | statusEffectQueue.statusEffectFrame->setHollow(true); | |||
| 5590 | statusEffectQueue.statusEffectFrame->setBorder(0); | |||
| 5591 | statusEffectQueue.statusEffectFrame->setOwner(player); | |||
| 5592 | statusEffectQueue.statusEffectFrame->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 5593 | ||||
| 5594 | auto automatonHungerFrame = statusEffectQueue.statusEffectFrame->addFrame("automaton hunger notification"); | |||
| 5595 | automatonHungerFrame->setHollow(true); | |||
| 5596 | automatonHungerFrame->setDisabled(true); | |||
| 5597 | automatonHungerFrame->setSize(SDL_Rect{ 0, 0, 64, 64 }); | |||
| 5598 | auto automaton_flame_img = automatonHungerFrame->addImage(SDL_Rect{ 0, 0, 64, 64 }, 0xFFFFFFFF, "images/system/Hunger_boiler_fire.png", "flame"); | |||
| 5599 | ||||
| 5600 | auto notif_frame = statusEffectQueue.statusEffectFrame->addFrame("notification frame"); | |||
| 5601 | notif_frame->setHollow(true); | |||
| 5602 | notif_frame->setDisabled(true); | |||
| 5603 | notif_frame->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 5604 | auto notif = notif_frame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "images/system/white.png", "notification img"); | |||
| 5605 | notif->disabled = true; | |||
| 5606 | auto notif_txt = notif_frame->addField("notification txt", 128); | |||
| 5607 | //notif_txt->setFont("fonts/pixel_maz_multiline.ttf#16#2"); | |||
| 5608 | notif_txt->setFont("fonts/pixelmix.ttf#16#2"); | |||
| 5609 | notif_txt->setText(""); | |||
| 5610 | notif_txt->setDisabled(true); | |||
| 5611 | notif_txt->setColor(makeColor(255, 255, 255, 255)); | |||
| 5612 | notif_txt->setVJustify(Field::justify_t::CENTER); | |||
| 5613 | notif_txt->setHJustify(Field::justify_t::CENTER); | |||
| 5614 | ||||
| 5615 | auto innerFrame = statusEffectQueue.statusEffectFrame->addFrame("effects"); | |||
| 5616 | innerFrame->setHollow(true); | |||
| 5617 | } | |||
| 5618 | ||||
| 5619 | const int breadStatusEffectHeight = 60; | |||
| 5620 | ||||
| 5621 | std::string& StatusEffectQueue_t::EffectDefinitionEntry_t::getName(int variation) | |||
| 5622 | { | |||
| 5623 | if ( variation >= 0 ) | |||
| 5624 | { | |||
| 5625 | return nameVariations[std::min(variation, (int)nameVariations.size() - 1)]; | |||
| 5626 | } | |||
| 5627 | return name; | |||
| 5628 | } | |||
| 5629 | ||||
| 5630 | std::string& StatusEffectQueue_t::EffectDefinitionEntry_t::getDesc(int variation) | |||
| 5631 | { | |||
| 5632 | if ( variation >= 0 ) | |||
| 5633 | { | |||
| 5634 | return descVariations[std::min(variation, (int)descVariations.size() - 1)]; | |||
| 5635 | } | |||
| 5636 | return desc; | |||
| 5637 | } | |||
| 5638 | ||||
| 5639 | void StatusEffectQueue_t::createStatusEffectTooltip() | |||
| 5640 | { | |||
| 5641 | auto& tooltipFrame = statusEffectTooltipFrame; | |||
| 5642 | if ( tooltipFrame ) | |||
| 5643 | { | |||
| 5644 | return; | |||
| 5645 | } | |||
| 5646 | char name[32]; | |||
| 5647 | snprintf(name, sizeof(name), "player statusfx tooltip %d", player); | |||
| 5648 | tooltipFrame = gameUIFrame[player]->addFrame(name); | |||
| 5649 | tooltipFrame->setHollow(true); | |||
| 5650 | tooltipFrame->setDisabled(true); | |||
| 5651 | tooltipFrame->setInheritParentFrameOpacity(false); | |||
| 5652 | tooltipFrame->setBorder(0); | |||
| 5653 | tooltipFrame->setOwner(player); | |||
| 5654 | tooltipFrame->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 5655 | ||||
| 5656 | { | |||
| 5657 | Uint32 color = makeColor(255, 255, 255, 255); | |||
| 5658 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 5659 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TL_Blue_00.png", skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 5660 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 5661 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TR_Blue_00.png", skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 5662 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 5663 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_T_Blue_00.png", skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 5664 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 5665 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_L_00.png", skillsheetEffectBackgroundImages[MIDDLE_LEFT].c_str()); | |||
| 5666 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 5667 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_R_00.png", skillsheetEffectBackgroundImages[MIDDLE_RIGHT].c_str()); | |||
| 5668 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 5669 | makeColor(22, 24, 29, 255), "images/system/white.png", skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 5670 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 5671 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_BL_00.png", skillsheetEffectBackgroundImages[BOTTOM_LEFT].c_str()); | |||
| 5672 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 5673 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_BR_00.png", skillsheetEffectBackgroundImages[BOTTOM_RIGHT].c_str()); | |||
| 5674 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 5675 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_B_00.png", skillsheetEffectBackgroundImages[BOTTOM].c_str()); | |||
| 5676 | imageSetWidthHeight9x9(tooltipFrame, skillsheetEffectBackgroundImages); | |||
| 5677 | ||||
| 5678 | auto heading_txt = tooltipFrame->addField("heading txt", 128); | |||
| 5679 | heading_txt->setFont("fonts/pixel_maz_multiline.ttf#16#2"); | |||
| 5680 | heading_txt->setText(""); | |||
| 5681 | heading_txt->setColor(makeColor(255, 255, 255, 255)); | |||
| 5682 | heading_txt->setVJustify(Field::justify_t::CENTER); | |||
| 5683 | heading_txt->setHJustify(Field::justify_t::LEFT); | |||
| 5684 | ||||
| 5685 | auto desc_txt = tooltipFrame->addField("desc txt", 1024); | |||
| 5686 | desc_txt->setFont("fonts/pixel_maz_multiline.ttf#16#2"); | |||
| 5687 | desc_txt->setText(""); | |||
| 5688 | desc_txt->setColor(makeColor(0, 192, 255, 255)); | |||
| 5689 | desc_txt->setVJustify(Field::justify_t::LEFT); | |||
| 5690 | desc_txt->setHJustify(Field::justify_t::LEFT); | |||
| 5691 | } | |||
| 5692 | } | |||
| 5693 | ||||
| 5694 | void Player::HUD_t::updateStatusEffectTooltip() | |||
| 5695 | { | |||
| 5696 | StatusEffectQueue[player.playernum].createStatusEffectTooltip(); | |||
| 5697 | } | |||
| 5698 | ||||
| 5699 | void Player::HUD_t::closeStatusFxWindow() | |||
| 5700 | { | |||
| 5701 | bool wasActive = statusFxFocusedWindowActive; | |||
| 5702 | statusFxFocusedWindowActive = false; | |||
| 5703 | ||||
| 5704 | StatusEffectQueue[player.playernum].focusedWindowAnim = 0.0; | |||
| 5705 | if ( statusEffectFocusedWindow ) | |||
| 5706 | { | |||
| 5707 | statusEffectFocusedWindow->setDisabled(true); | |||
| 5708 | } | |||
| 5709 | if ( StatusEffectQueue[player.playernum].statusEffectFrame ) | |||
| 5710 | { | |||
| 5711 | StatusEffectQueue[player.playernum].statusEffectFrame->setDisabled(false); | |||
| 5712 | } | |||
| 5713 | ||||
| 5714 | if ( wasActive ) | |||
| 5715 | { | |||
| 5716 | player.GUI.returnToPreviousActiveModule(); | |||
| 5717 | } | |||
| 5718 | } | |||
| 5719 | ||||
| 5720 | void Player::HUD_t::updateStatusEffectFocusedWindow() | |||
| 5721 | { | |||
| 5722 | if ( !statusEffectFocusedWindow ) | |||
| 5723 | { | |||
| 5724 | char name[32]; | |||
| 5725 | snprintf(name, sizeof(name), "player statusfx window %d", player.playernum); | |||
| 5726 | statusEffectFocusedWindow = gameUIFrame[player.playernum]->addFrame(name); | |||
| 5727 | statusEffectFocusedWindow->setHollow(false); | |||
| 5728 | statusEffectFocusedWindow->setBorder(0); | |||
| 5729 | statusEffectFocusedWindow->setOwner(player.playernum); | |||
| 5730 | statusEffectFocusedWindow->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 5731 | statusEffectFocusedWindow->setDisabled(true); | |||
| 5732 | ||||
| 5733 | /*auto img = statusEffectFocusedWindow->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, | |||
| 5734 | "*#images/ui/HUD/statusfx/background_panel.png", "background"); | |||
| 5735 | img->disabled = false;*/ | |||
| 5736 | ||||
| 5737 | auto backgroundFrame = statusEffectFocusedWindow->addFrame("background frame"); | |||
| 5738 | { | |||
| 5739 | auto heading_txt = backgroundFrame->addField("heading txt", 128); | |||
| 5740 | heading_txt->setFont("fonts/pixel_maz_multiline.ttf#16#2"); | |||
| 5741 | heading_txt->setText(Language::get(4345)); | |||
| 5742 | heading_txt->setColor(makeColor(255, 255, 255, 255)); | |||
| 5743 | heading_txt->setVJustify(Field::justify_t::CENTER); | |||
| 5744 | heading_txt->setHJustify(Field::justify_t::CENTER); | |||
| 5745 | heading_txt->setSize(SDL_Rect{ 16, 2, 256, 30 }); | |||
| 5746 | heading_txt->setColor(hudColors.characterSheetNeutral); | |||
| 5747 | ||||
| 5748 | backgroundFrame->addImage(SDL_Rect{ 24, 0, 0, 30 }, | |||
| 5749 | 0xFFFFFFFF, "*#images/ui/Inventory/tooltips/HoverFxMenu_T03.png", skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 5750 | backgroundFrame->addImage(SDL_Rect{ 0, 0, 24, 30 }, | |||
| 5751 | 0xFFFFFFFF, "*#images/ui/Inventory/tooltips/HoverFxMenu_TL03.png", skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 5752 | backgroundFrame->addImage(SDL_Rect{ 0, 0, 24, 30 }, | |||
| 5753 | 0xFFFFFFFF, "*#images/ui/Inventory/tooltips/HoverFxMenu_TR03.png", skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 5754 | backgroundFrame->addImage(SDL_Rect{ 24, 30, 0, 12 }, | |||
| 5755 | makeColor(22, 24, 29, 255), | |||
| 5756 | "*#images/ui/Inventory/tooltips/HoverFxMenu_C03.png", skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 5757 | auto ml = backgroundFrame->addImage(SDL_Rect{ 0, 30, 24, 12 }, | |||
| 5758 | 0xFFFFFFFF, "*#images/ui/Inventory/tooltips/HoverFxMenu_L03.png", skillsheetEffectBackgroundImages[MIDDLE_LEFT].c_str()); | |||
| 5759 | ml->tiled = true; | |||
| 5760 | auto mr = backgroundFrame->addImage(SDL_Rect{ 0, 30, 24, 12 }, | |||
| 5761 | 0xFFFFFFFF, "*#images/ui/Inventory/tooltips/HoverFxMenu_R03.png", skillsheetEffectBackgroundImages[MIDDLE_RIGHT].c_str()); | |||
| 5762 | mr->tiled = true; | |||
| 5763 | ||||
| 5764 | backgroundFrame->addImage(SDL_Rect{ 24, 96, 0, 14 }, | |||
| 5765 | 0xFFFFFFFF, "*#images/ui/Inventory/tooltips/HoverFxMenu_B03.png", skillsheetEffectBackgroundImages[BOTTOM].c_str()); | |||
| 5766 | backgroundFrame->addImage(SDL_Rect{ 0, 96, 24, 14 }, | |||
| 5767 | 0xFFFFFFFF, "*#images/ui/Inventory/tooltips/HoverFxMenu_BL03.png", skillsheetEffectBackgroundImages[BOTTOM_LEFT].c_str()); | |||
| 5768 | backgroundFrame->addImage(SDL_Rect{ 0, 96, 24, 14 }, | |||
| 5769 | 0xFFFFFFFF, "*#images/ui/Inventory/tooltips/HoverFxMenu_BR03.png", skillsheetEffectBackgroundImages[BOTTOM_RIGHT].c_str()); | |||
| 5770 | ||||
| 5771 | auto dismiss = backgroundFrame->addButton("dismiss button"); | |||
| 5772 | dismiss->setSize(SDL_Rect{ 0, 0, 90, 34 }); | |||
| 5773 | dismiss->setColor(makeColor(255, 255, 255, 255)); | |||
| 5774 | dismiss->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 5775 | dismiss->setBackground("*#images/ui/Inventory/chests/Button_TakeAll_00.png"); | |||
| 5776 | dismiss->setBackgroundHighlighted("*#images/ui/Inventory/chests/Button_TakeAllHigh_00.png"); | |||
| 5777 | dismiss->setBackgroundActivated("*#images/ui/Inventory/chests/Button_TakeAllPress_00.png"); | |||
| 5778 | dismiss->setText(Language::get(5835)); | |||
| 5779 | dismiss->setFont(smallfont_outline); | |||
| 5780 | dismiss->setTextHighlightColor(makeColor(201, 162, 100, 255)); | |||
| 5781 | dismiss->setDisabled(true); | |||
| 5782 | dismiss->setHideGlyphs(true); | |||
| 5783 | dismiss->setHideKeyboardGlyphs(true); | |||
| 5784 | dismiss->setMenuConfirmControlType(0); | |||
| 5785 | dismiss->setHideSelectors(true); | |||
| 5786 | dismiss->setOntop(true); | |||
| 5787 | dismiss->setCallback([](Button& button) { | |||
| 5788 | players[button.getOwner()]->hud.closeStatusFxWindow(); | |||
| 5789 | Player::soundCancel(); | |||
| 5790 | }); | |||
| 5791 | ||||
| 5792 | auto noEffectTxt = backgroundFrame->addField("no effect txt", 128); | |||
| 5793 | noEffectTxt->setFont(smallfont_outline); | |||
| 5794 | noEffectTxt->setText(Language::get(4346)); | |||
| 5795 | noEffectTxt->setDisabled(true); | |||
| 5796 | noEffectTxt->setColor(makeColor(255, 255, 255, 255)); | |||
| 5797 | noEffectTxt->setVJustify(Field::justify_t::CENTER); | |||
| 5798 | noEffectTxt->setHJustify(Field::justify_t::CENTER); | |||
| 5799 | } | |||
| 5800 | ||||
| 5801 | auto automatonHungerFrame = statusEffectFocusedWindow->addFrame("automaton hunger notification"); | |||
| 5802 | automatonHungerFrame->setHollow(true); | |||
| 5803 | automatonHungerFrame->setDisabled(true); | |||
| 5804 | automatonHungerFrame->setSize(SDL_Rect{ 0, 0, 64, 64 }); | |||
| 5805 | auto automaton_flame_img = automatonHungerFrame->addImage(SDL_Rect{ 0, 0, 64, 64 }, 0xFFFFFFFF, "images/system/Hunger_boiler_fire.png", "flame"); | |||
| 5806 | ||||
| 5807 | auto notif_frame = statusEffectFocusedWindow->addFrame("notification frame"); | |||
| 5808 | notif_frame->setHollow(true); | |||
| 5809 | notif_frame->setDisabled(true); | |||
| 5810 | notif_frame->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 5811 | auto notif = notif_frame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "images/system/white.png", "notification img"); | |||
| 5812 | notif->disabled = true; | |||
| 5813 | auto notif_txt = notif_frame->addField("notification txt", 128); | |||
| 5814 | //notif_txt->setFont("fonts/pixel_maz_multiline.ttf#16#2"); | |||
| 5815 | notif_txt->setFont("fonts/pixelmix.ttf#16#2"); | |||
| 5816 | notif_txt->setText(""); | |||
| 5817 | notif_txt->setDisabled(true); | |||
| 5818 | notif_txt->setColor(makeColor(255, 255, 255, 255)); | |||
| 5819 | notif_txt->setVJustify(Field::justify_t::CENTER); | |||
| 5820 | notif_txt->setHJustify(Field::justify_t::CENTER); | |||
| 5821 | ||||
| 5822 | auto innerFrame = statusEffectFocusedWindow->addFrame("effects"); | |||
| 5823 | innerFrame->setHollow(true); | |||
| 5824 | } | |||
| 5825 | ||||
| 5826 | auto& animBackground = StatusEffectQueue[player.playernum].focusedWindowAnim; | |||
| 5827 | if ( player.shootmode | |||
| 5828 | || player.inventory_mode != INVENTORY_MODE_ITEM | |||
| 5829 | || (player.inventoryUI.bCompactView && compactLayoutMode != COMPACT_LAYOUT_INVENTORY) ) | |||
| 5830 | { | |||
| 5831 | closeStatusFxWindow(); | |||
| 5832 | return; | |||
| 5833 | } | |||
| 5834 | /*if ( enableDebugKeys && keystatus[SDLK_g] ) | |||
| 5835 | { | |||
| 5836 | statusFxFocusedWindowActive = true; | |||
| 5837 | }*/ | |||
| 5838 | statusEffectFocusedWindow->setDisabled(true); | |||
| 5839 | if ( StatusEffectQueue[player.playernum].statusEffectFrame && statusFxFocusedWindowActive ) | |||
| 5840 | { | |||
| 5841 | statusEffectFocusedWindow->setDisabled(false); | |||
| 5842 | StatusEffectQueue[player.playernum].statusEffectFrame->setDisabled(true); | |||
| 5843 | ||||
| 5844 | Frame* srcFrame = StatusEffectQueue[player.playernum].statusEffectFrame; | |||
| 5845 | Frame* destFrame = statusEffectFocusedWindow; | |||
| 5846 | destFrame->setSize(SDL_Rect{ player.camera_virtualx1(), | |||
| 5847 | player.camera_virtualy1(), | |||
| 5848 | player.camera_virtualWidth(), | |||
| 5849 | player.camera_virtualHeight() }); | |||
| 5850 | ||||
| 5851 | const int offsetH = 6; | |||
| 5852 | ||||
| 5853 | SDL_Rect destPos = destFrame->getSize(); | |||
| 5854 | destPos.h += offsetH; | |||
| 5855 | destFrame->setSize(destPos); | |||
| 5856 | ||||
| 5857 | ||||
| 5858 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 5859 | real_t setpointDiffX = fpsScale * std::max(.1, (1.0 - animBackground)) / (2.5); | |||
| 5860 | ||||
| 5861 | animBackground += setpointDiffX; | |||
| 5862 | animBackground = std::min(1.0, animBackground); | |||
| 5863 | ||||
| 5864 | size_t f = 0; | |||
| 5865 | for ( auto srcf : srcFrame->getFrames() ) | |||
| 5866 | { | |||
| 5867 | Frame* destf = destFrame->getFrames()[f]; | |||
| 5868 | if ( !strcmp(destf->getName(), "background frame") ) | |||
| 5869 | { | |||
| 5870 | ++f; | |||
| 5871 | destf = destFrame->getFrames()[f]; | |||
| 5872 | } | |||
| 5873 | ||||
| 5874 | SDL_Rect srcSize = srcf->getSize(); | |||
| 5875 | srcSize.x += srcFrame->getSize().x; | |||
| 5876 | srcSize.y += srcFrame->getSize().y; | |||
| 5877 | destf->setSize(srcSize); | |||
| 5878 | destf->setDisabled(srcf->isDisabled()); | |||
| 5879 | ||||
| 5880 | if ( !strcmp(srcf->getName(), "effects") ) | |||
| 5881 | { | |||
| 5882 | int numFrameImages = srcf->getImages().size(); | |||
| 5883 | while ( destf->getImages().size() < numFrameImages ) | |||
| 5884 | { | |||
| 5885 | auto img = destf->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "inner img"); | |||
| 5886 | img->disabled = true; | |||
| 5887 | } | |||
| 5888 | while ( destf->getImages().size() > numFrameImages ) | |||
| 5889 | { | |||
| 5890 | destf->getImages().erase(destf->getImages().begin()); | |||
| 5891 | numFrameImages = destf->getImages().size(); | |||
| 5892 | } | |||
| 5893 | } | |||
| 5894 | ||||
| 5895 | size_t i = 0; | |||
| 5896 | for ( auto srcImg : srcf->getImages() ) | |||
| 5897 | { | |||
| 5898 | auto destImg = destf->getImages()[i]; | |||
| 5899 | destImg->pos = srcImg->pos; | |||
| 5900 | destImg->path = srcImg->path; | |||
| 5901 | destImg->disabled = srcImg->disabled; | |||
| 5902 | ++i; | |||
| 5903 | } | |||
| 5904 | ||||
| 5905 | size_t t = 0; | |||
| 5906 | for ( auto srcTxt : srcf->getFields() ) | |||
| 5907 | { | |||
| 5908 | auto destTxt = destf->getFields()[t]; | |||
| 5909 | destTxt->setText(srcTxt->getText()); | |||
| 5910 | destTxt->setSize(srcTxt->getSize()); | |||
| 5911 | destTxt->setDisabled(srcTxt->isDisabled()); | |||
| 5912 | ++t; | |||
| 5913 | } | |||
| 5914 | ++f; | |||
| 5915 | } | |||
| 5916 | ||||
| 5917 | auto& effectQueue = StatusEffectQueue[player.playernum].effectQueue; | |||
| 5918 | auto bgFrame = destFrame->findFrame("background frame"); | |||
| 5919 | SDL_Rect bgPos{ 0, 0, | |||
| 5920 | std::max(126, StatusEffectQueue[player.playernum].effectsBoundingBox.w), | |||
| 5921 | std::max(32, StatusEffectQueue[player.playernum].effectsBoundingBox.y - | |||
| 5922 | StatusEffectQueue[player.playernum].effectsBoundingBox.h)}; | |||
| 5923 | if ( effectQueue.size() == 0 ) | |||
| 5924 | { | |||
| 5925 | bgPos.w = std::max(bgPos.w, 126 + 18); | |||
| 5926 | bgPos.h = std::max(bgPos.h, 32 + 24); | |||
| 5927 | } | |||
| 5928 | { | |||
| 5929 | bgPos.h += 42; | |||
| 5930 | bgPos.w += 28; | |||
| 5931 | int startx = std::max(4, player.hud.hpFrame->getSize().x - 4); | |||
| 5932 | bgPos.x = -(bgPos.w) + (bgPos.w + startx) * animBackground; | |||
| 5933 | //bgPos.x = startx; | |||
| 5934 | bgFrame->setInheritParentFrameOpacity(false); | |||
| 5935 | bgFrame->setOpacity(animBackground * 100.0); | |||
| 5936 | bgFrame->setSize(bgPos); | |||
| 5937 | ||||
| 5938 | int maxHeight = bgPos.h; | |||
| 5939 | int interimHeight = 0; | |||
| 5940 | { | |||
| 5941 | auto tl = bgFrame->findImage(skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 5942 | auto tmid = bgFrame->findImage(skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 5943 | tmid->pos.w = bgPos.w - tl->pos.w * 2; | |||
| 5944 | auto tr = bgFrame->findImage(skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 5945 | tr->pos.x = tmid->pos.x + tmid->pos.w; | |||
| 5946 | ||||
| 5947 | interimHeight = tmid->pos.y + tmid->pos.h; | |||
| 5948 | bgPos.w = tr->pos.x + tr->pos.w; | |||
| 5949 | } | |||
| 5950 | { | |||
| 5951 | const int middleOffsetY = 12; | |||
| 5952 | auto ml = bgFrame->findImage(skillsheetEffectBackgroundImages[MIDDLE_LEFT].c_str()); | |||
| 5953 | ml->pos.h = maxHeight - interimHeight - middleOffsetY; | |||
| 5954 | auto mmid = bgFrame->findImage(skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 5955 | mmid->pos.h = ml->pos.h; | |||
| 5956 | mmid->pos.w = bgPos.w - (ml->pos.w) * 2; | |||
| 5957 | mmid->color = hudColors.itemContextMenuOptionImg; | |||
| 5958 | auto mr = bgFrame->findImage(skillsheetEffectBackgroundImages[MIDDLE_RIGHT].c_str()); | |||
| 5959 | mr->pos.h = ml->pos.h; | |||
| 5960 | mr->pos.x = mmid->pos.x + mmid->pos.w; | |||
| 5961 | ||||
| 5962 | interimHeight = mmid->pos.y + mmid->pos.h; | |||
| 5963 | } | |||
| 5964 | { | |||
| 5965 | auto bl = bgFrame->findImage(skillsheetEffectBackgroundImages[BOTTOM_LEFT].c_str()); | |||
| 5966 | bl->pos.y = interimHeight; | |||
| 5967 | auto bmid = bgFrame->findImage(skillsheetEffectBackgroundImages[BOTTOM].c_str()); | |||
| 5968 | bmid->pos.y = interimHeight; | |||
| 5969 | bmid->pos.w = bgPos.w - bl->pos.w * 2; | |||
| 5970 | auto br = bgFrame->findImage(skillsheetEffectBackgroundImages[BOTTOM_RIGHT].c_str()); | |||
| 5971 | br->pos.y = interimHeight; | |||
| 5972 | br->pos.x = bmid->pos.x + bmid->pos.w; | |||
| 5973 | ||||
| 5974 | bgPos.h = br->pos.y + br->pos.h; | |||
| 5975 | } | |||
| 5976 | bgPos.y = srcFrame->getSize().y + (srcFrame->getSize().h - bgPos.h + offsetH); | |||
| 5977 | bgPos.y += 4; | |||
| 5978 | bgFrame->setSize(bgPos); | |||
| 5979 | } | |||
| 5980 | ||||
| 5981 | auto dismiss = bgFrame->findButton("dismiss button"); | |||
| 5982 | dismiss->setDisabled(true); | |||
| 5983 | auto noEffectTxt = bgFrame->findField("no effect txt"); | |||
| 5984 | noEffectTxt->setDisabled(true); | |||
| 5985 | if ( effectQueue.size() == 0 ) | |||
| 5986 | { | |||
| 5987 | dismiss->setDisabled(false); | |||
| 5988 | noEffectTxt->setDisabled(false); | |||
| 5989 | } | |||
| 5990 | if ( inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 5991 | { | |||
| 5992 | if ( Input::inputs[player.playernum].binaryToggle("MenuLeftClick") && inputs.bPlayerUsingKeyboardControl(player.playernum) ) | |||
| 5993 | { | |||
| 5994 | Input::inputs[player.playernum].consumeBinaryToggle("MenuLeftClick"); | |||
| 5995 | if ( !bgFrame->capturesMouse() ) | |||
| 5996 | { | |||
| 5997 | closeStatusFxWindow(); | |||
| 5998 | Player::soundCancel(); | |||
| 5999 | return; | |||
| 6000 | } | |||
| 6001 | } | |||
| 6002 | } | |||
| 6003 | else | |||
| 6004 | { | |||
| 6005 | if ( StatusEffectQueue[player.playernum].statusEffectTooltipFrame ) | |||
| 6006 | { | |||
| 6007 | SDL_Rect tooltipPos = StatusEffectQueue[player.playernum].statusEffectTooltipFrame->getSize(); | |||
| 6008 | ||||
| 6009 | SDL_Rect tooltipAbsoluteSize = StatusEffectQueue[player.playernum].statusEffectTooltipFrame->getAbsoluteSize(); | |||
| 6010 | SDL_Rect bgAbsoluteSize = bgFrame->getAbsoluteSize(); | |||
| 6011 | ||||
| 6012 | int positionDiffX = tooltipAbsoluteSize.x; | |||
| 6013 | positionDiffX -= (bgAbsoluteSize.x + bgAbsoluteSize.w + 4); | |||
| 6014 | int positionDiffY = tooltipAbsoluteSize.y; | |||
| 6015 | positionDiffY -= (bgAbsoluteSize.y); | |||
| 6016 | ||||
| 6017 | tooltipPos.x = std::max(tooltipPos.x, tooltipPos.x - positionDiffX); | |||
| 6018 | tooltipPos.y -= positionDiffY; | |||
| 6019 | int overflow = tooltipPos.y + tooltipPos.h - player.camera_virtualy2(); | |||
| 6020 | if ( overflow > 0 ) | |||
| 6021 | { | |||
| 6022 | tooltipPos.y -= overflow; | |||
| 6023 | } | |||
| 6024 | ||||
| 6025 | StatusEffectQueue[player.playernum].statusEffectTooltipFrame->setSize(tooltipPos); | |||
| 6026 | } | |||
| 6027 | } | |||
| 6028 | ||||
| 6029 | if ( inputs.hasController(player.playernum) ) | |||
| 6030 | { | |||
| 6031 | if ( Input::inputs[player.playernum].binaryToggle("MenuCancel") | |||
| 6032 | || Input::inputs[player.playernum].binaryToggle("MenuConfirm") ) | |||
| 6033 | { | |||
| 6034 | Input::inputs[player.playernum].consumeBinaryToggle("MenuCancel"); | |||
| 6035 | Input::inputs[player.playernum].consumeBinaryToggle("MenuConfirm"); | |||
| 6036 | closeStatusFxWindow(); | |||
| 6037 | Player::soundCancel(); | |||
| 6038 | return; | |||
| 6039 | } | |||
| 6040 | } | |||
| 6041 | ||||
| 6042 | if ( player.GUI.bModuleAccessibleWithMouse(Player::GUI_t::MODULE_STATUS_EFFECTS) ) | |||
| 6043 | { | |||
| 6044 | if ( (dismiss->isHighlighted() || !inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 6045 | && !dismiss->isDisabled() && animBackground >= 0.99 ) | |||
| 6046 | { | |||
| 6047 | player.GUI.setHoveringOverModuleButton(Player::GUI_t::MODULE_STATUS_EFFECTS); | |||
| 6048 | if ( player.GUI.activeModule != Player::GUI_t::MODULE_STATUS_EFFECTS ) | |||
| 6049 | { | |||
| 6050 | player.GUI.activateModule(Player::GUI_t::MODULE_STATUS_EFFECTS); | |||
| 6051 | } | |||
| 6052 | SDL_Rect pos = dismiss->getAbsoluteSize(); | |||
| 6053 | // make sure to adjust absolute size to camera viewport | |||
| 6054 | pos.x -= player.camera_virtualx1(); | |||
| 6055 | pos.y -= player.camera_virtualy1(); | |||
| 6056 | ||||
| 6057 | player.hud.setCursorDisabled(false); | |||
| 6058 | player.hud.updateCursorAnimation(pos.x - 1, pos.y - 1, pos.w, pos.h, inputs.getVirtualMouse(player.playernum)->draw_cursor); | |||
| 6059 | } | |||
| 6060 | } | |||
| 6061 | ||||
| 6062 | { | |||
| 6063 | SDL_Rect btnSize = dismiss->getSize(); | |||
| 6064 | dismiss->setSize(SDL_Rect{ bgPos.w / 2 - btnSize.w / 2, | |||
| 6065 | bgPos.h - btnSize.h - 8, btnSize.w, btnSize.h }); | |||
| 6066 | SDL_Rect txtSize = noEffectTxt->getSize(); | |||
| 6067 | txtSize.w = bgPos.w; | |||
| 6068 | txtSize.h = 24; | |||
| 6069 | txtSize.x = 0; | |||
| 6070 | txtSize.y = btnSize.y - 24; | |||
| 6071 | if ( txtSize.y % 2 == 1 ) | |||
| 6072 | { | |||
| 6073 | txtSize.y--; | |||
| 6074 | } | |||
| 6075 | ||||
| 6076 | auto heading_txt = bgFrame->findField("heading txt"); | |||
| 6077 | SDL_Rect headerTxtSize = heading_txt->getSize(); | |||
| 6078 | headerTxtSize.w = bgPos.w; | |||
| 6079 | headerTxtSize.x = 0; | |||
| 6080 | heading_txt->setSize(headerTxtSize); | |||
| 6081 | ||||
| 6082 | noEffectTxt->setSize(txtSize); | |||
| 6083 | dismiss->setInvisible(dismiss->isDisabled()); | |||
| 6084 | } | |||
| 6085 | } | |||
| 6086 | else | |||
| 6087 | { | |||
| 6088 | closeStatusFxWindow(); | |||
| 6089 | return; | |||
| 6090 | } | |||
| 6091 | ||||
| 6092 | if ( player.hud.hudFrame && player.hud.hudFrame->isDisabled() ) | |||
| 6093 | { | |||
| 6094 | closeStatusFxWindow(); | |||
| 6095 | return; | |||
| 6096 | } | |||
| 6097 | return; | |||
| 6098 | //Frame* fxFrame = nullptr; | |||
| 6099 | //if ( !statusEffectFocusedWindow ) | |||
| 6100 | //{ | |||
| 6101 | // char name[32]; | |||
| 6102 | // snprintf(name, sizeof(name), "player statusfx window %d", player.playernum); | |||
| 6103 | // statusEffectFocusedWindow = gameUIFrame[player.playernum]->addFrame(name); | |||
| 6104 | // Frame* frame = statusEffectFocusedWindow; | |||
| 6105 | // frame->setHollow(false); | |||
| 6106 | // frame->setDisabled(true); | |||
| 6107 | // frame->setInheritParentFrameOpacity(true); | |||
| 6108 | // frame->setBorder(0); | |||
| 6109 | // frame->setOwner(player.playernum); | |||
| 6110 | // frame->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 6111 | ||||
| 6112 | // { | |||
| 6113 | // Uint32 color = makeColor(255, 255, 255, 255); | |||
| 6114 | // frame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 6115 | // color, "*#images/ui/Inventory/tooltips/HoverItemMenu_TL03.png", skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 6116 | // frame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 6117 | // color, "*#images/ui/Inventory/tooltips/HoverItemMenu_TR03.png", skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 6118 | // frame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 6119 | // color, "*#images/ui/Inventory/tooltips/HoverItemMenu_T03.png", skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 6120 | // frame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 6121 | // color, "*#images/ui/Inventory/tooltips/HoverItemMenu_L03.png", skillsheetEffectBackgroundImages[MIDDLE_LEFT].c_str()); | |||
| 6122 | // frame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 6123 | // color, "*#images/ui/Inventory/tooltips/HoverItemMenu_R03.png", skillsheetEffectBackgroundImages[MIDDLE_RIGHT].c_str()); | |||
| 6124 | // frame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 6125 | // makeColor(22, 24, 29, 255), "*#images/ui/Inventory/tooltips/HoverItemMenu_C03.png", skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 6126 | // frame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 6127 | // color, "*#images/ui/Inventory/tooltips/HoverItemMenu_BL03.png", skillsheetEffectBackgroundImages[BOTTOM_LEFT].c_str()); | |||
| 6128 | // frame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 6129 | // color, "*#images/ui/Inventory/tooltips/HoverItemMenu_BR03.png", skillsheetEffectBackgroundImages[BOTTOM_RIGHT].c_str()); | |||
| 6130 | // frame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 6131 | // color, "*#images/ui/Inventory/tooltips/HoverItemMenu_B03.png", skillsheetEffectBackgroundImages[BOTTOM].c_str()); | |||
| 6132 | // imageSetWidthHeight9x9(frame, skillsheetEffectBackgroundImages); | |||
| 6133 | ||||
| 6134 | // auto heading_txt = frame->addField("heading txt", 128); | |||
| 6135 | // heading_txt->setFont("fonts/pixel_maz_multiline.ttf#16#2"); | |||
| 6136 | // heading_txt->setText("Status Effects"); | |||
| 6137 | // heading_txt->setColor(makeColor(255, 255, 255, 255)); | |||
| 6138 | // heading_txt->setVJustify(Field::justify_t::CENTER); | |||
| 6139 | // heading_txt->setHJustify(Field::justify_t::LEFT); | |||
| 6140 | // /* | |||
| 6141 | // auto desc_txt = tooltipFrame->addField("desc txt", 1024); | |||
| 6142 | // desc_txt->setFont("fonts/pixel_maz_multiline.ttf#16#2"); | |||
| 6143 | // desc_txt->setText(""); | |||
| 6144 | // desc_txt->setColor(makeColor(0, 192, 255, 255)); | |||
| 6145 | // desc_txt->setVJustify(Field::justify_t::LEFT); | |||
| 6146 | // desc_txt->setHJustify(Field::justify_t::LEFT);*/ | |||
| 6147 | // } | |||
| 6148 | ||||
| 6149 | // auto automatonBgFrame = frame->addFrame("automaton bg"); | |||
| 6150 | // automatonBgFrame->setSize(SDL_Rect{ 0, 0, 64, 64 }); | |||
| 6151 | // automatonBgFrame->setDisabled(true); | |||
| 6152 | // automatonBgFrame->addImage(SDL_Rect{ 0, 0, 64, 64 }, 0xFFFFFFFF, "", "flame"); | |||
| 6153 | ||||
| 6154 | // fxFrame = frame->addFrame("effects"); | |||
| 6155 | //} | |||
| 6156 | //else | |||
| 6157 | //{ | |||
| 6158 | // fxFrame = statusEffectFocusedWindow->findFrame("effects"); | |||
| 6159 | //} | |||
| 6160 | ||||
| 6161 | //bool rebuildWindow = true; | |||
| 6162 | //if ( keystatus[SDLK_g] ) | |||
| 6163 | //{ | |||
| 6164 | // keystatus[SDLK_g] = 0; | |||
| 6165 | // if ( statusEffectFocusedWindow->isDisabled() ) | |||
| 6166 | // { | |||
| 6167 | // statusEffectFocusedWindow->setDisabled(false); | |||
| 6168 | // rebuildWindow = true; | |||
| 6169 | // } | |||
| 6170 | // else | |||
| 6171 | // { | |||
| 6172 | // statusEffectFocusedWindow->setDisabled(true); | |||
| 6173 | // } | |||
| 6174 | //} | |||
| 6175 | ||||
| 6176 | //if ( rebuildWindow && StatusEffectQueue[player.playernum].statusEffectFrame ) | |||
| 6177 | //{ | |||
| 6178 | // statusEffectFocusedWindow->setDisabled(false); | |||
| 6179 | // auto& effectQueue = StatusEffectQueue[player.playernum].effectQueue; | |||
| 6180 | // auto& notificationQueue = StatusEffectQueue[player.playernum].notificationQueue; | |||
| 6181 | // auto statusFx = StatusEffectQueue[player.playernum].statusEffectFrame->findFrame("effects"); | |||
| 6182 | ||||
| 6183 | // statusEffectFocusedWindow->setSize(statusFx->getSize()); | |||
| 6184 | // fxFrame->setSize(statusFx->getSize()); | |||
| 6185 | ||||
| 6186 | // int numFrameImages = fxFrame->getImages().size(); | |||
| 6187 | // while ( effectQueue.size() > numFrameImages ) | |||
| 6188 | // { | |||
| 6189 | // auto img = fxFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "inner img"); | |||
| 6190 | // img->disabled = true; | |||
| 6191 | // numFrameImages = fxFrame->getImages().size(); | |||
| 6192 | // } | |||
| 6193 | // while ( effectQueue.size() < numFrameImages ) | |||
| 6194 | // { | |||
| 6195 | // fxFrame->getImages().erase(fxFrame->getImages().begin()); | |||
| 6196 | // numFrameImages = fxFrame->getImages().size(); | |||
| 6197 | // } | |||
| 6198 | // auto& frameImages = fxFrame->getImages(); | |||
| 6199 | // for ( auto img : frameImages ) | |||
| 6200 | // { | |||
| 6201 | // img->disabled = true; | |||
| 6202 | // } | |||
| 6203 | ||||
| 6204 | // auto automatonHungerFrame = statusEffectFocusedWindow->findFrame("automaton bg"); | |||
| 6205 | // auto flameImg = automatonHungerFrame->findImage("flame"); | |||
| 6206 | // automatonHungerFrame->setDisabled(true); | |||
| 6207 | // auto frameImagesIterator = frameImages.begin(); | |||
| 6208 | // auto srcFrameImagesIterator = statusFx->getImages().begin(); | |||
| 6209 | // size_t index = 0; | |||
| 6210 | // SDL_Rect windowSizeLimitMin{ 0, 0, 0, 0 }; | |||
| 6211 | // SDL_Rect windowSizeLimitMax{ 0, 0, 0, 0 }; | |||
| 6212 | // for ( auto it = effectQueue.rbegin(); it != effectQueue.rend(); ) | |||
| 6213 | // { | |||
| 6214 | // auto& q = (*it); | |||
| 6215 | // Frame::image_t* frameImg = nullptr; | |||
| 6216 | // Frame::image_t* srcFrameImg = nullptr; | |||
| 6217 | // if ( frameImagesIterator != frameImages.end() ) | |||
| 6218 | // { | |||
| 6219 | // frameImg = *frameImagesIterator; | |||
| 6220 | // } | |||
| 6221 | // if ( srcFrameImagesIterator != statusFx->getImages().end() ) | |||
| 6222 | // { | |||
| 6223 | // srcFrameImg = *srcFrameImagesIterator; | |||
| 6224 | // } | |||
| 6225 | ||||
| 6226 | // bool existsInNotifications = false; | |||
| 6227 | // for ( auto it2 = notificationQueue.begin(); it2 != notificationQueue.end(); ++it2 ) | |||
| 6228 | // { | |||
| 6229 | // if ( (*it2).effect == q.effect ) | |||
| 6230 | // { | |||
| 6231 | // existsInNotifications = true; | |||
| 6232 | // break; | |||
| 6233 | // } | |||
| 6234 | // } | |||
| 6235 | ||||
| 6236 | // StatusEffectQueue[player.playernum].updateEntryImage(q, frameImg); | |||
| 6237 | // frameImg->pos.x = q.animateSetpointX; | |||
| 6238 | // frameImg->pos.y = q.animateSetpointY; | |||
| 6239 | // frameImg->disabled = (srcFrameImg && !existsInNotifications) ? srcFrameImg->disabled : false; | |||
| 6240 | ||||
| 6241 | // if ( windowSizeLimitMin.x == 0 && index == 0 ) | |||
| 6242 | // { | |||
| 6243 | // windowSizeLimitMin.x = frameImg->pos.x; | |||
| 6244 | // } | |||
| 6245 | // else | |||
| 6246 | // { | |||
| 6247 | // windowSizeLimitMin.x = std::min(frameImg->pos.x, windowSizeLimitMin.x); | |||
| 6248 | // } | |||
| 6249 | // if ( windowSizeLimitMin.y == 0 && index == 0 ) | |||
| 6250 | // { | |||
| 6251 | // windowSizeLimitMin.y = frameImg->pos.y; | |||
| 6252 | // } | |||
| 6253 | // else | |||
| 6254 | // { | |||
| 6255 | // windowSizeLimitMin.y = std::min(frameImg->pos.y, windowSizeLimitMin.y); | |||
| 6256 | // } | |||
| 6257 | // windowSizeLimitMax.x = std::max(frameImg->pos.x + frameImg->pos.w, windowSizeLimitMax.x); | |||
| 6258 | // windowSizeLimitMax.y = std::max(frameImg->pos.y + frameImg->pos.h, windowSizeLimitMax.y); | |||
| 6259 | ||||
| 6260 | // if ( q.effect == StatusEffectQueue_t::kEffectAutomatonHunger ) | |||
| 6261 | // { | |||
| 6262 | // auto srcFrame = StatusEffectQueue[player.playernum].statusEffectFrame->findFrame("automaton hunger notification"); | |||
| 6263 | // automatonHungerFrame->setDisabled(srcFrame->isDisabled()); | |||
| 6264 | ||||
| 6265 | // SDL_Rect pos = srcFrame->getSize(); | |||
| 6266 | // pos.x = q.animateSetpointX; | |||
| 6267 | // pos.y = q.animateSetpointY; | |||
| 6268 | ||||
| 6269 | // int heightDiff = q.getEffectSpriteNormalHeight() - pos.h; | |||
| 6270 | // pos.y += heightDiff; | |||
| 6271 | ||||
| 6272 | // automatonHungerFrame->setSize(pos); | |||
| 6273 | ||||
| 6274 | // auto srcImg = srcFrame->findImage("flame"); | |||
| 6275 | // flameImg->pos = SDL_Rect{ 0, -heightDiff, q.getEffectSpriteNormalWidth(), q.getEffectSpriteNormalHeight() }; | |||
| 6276 | // flameImg->path = srcImg->path; | |||
| 6277 | // flameImg->disabled = !existsInNotifications ? srcImg->disabled : false; | |||
| 6278 | // } | |||
| 6279 | ||||
| 6280 | // ++it; | |||
| 6281 | // if ( frameImagesIterator != frameImages.end() ) | |||
| 6282 | // { | |||
| 6283 | // ++frameImagesIterator; | |||
| 6284 | // } | |||
| 6285 | // if ( srcFrameImagesIterator != statusFx->getImages().end() ) | |||
| 6286 | // { | |||
| 6287 | // ++srcFrameImagesIterator; | |||
| 6288 | // } | |||
| 6289 | // ++index; | |||
| 6290 | // } | |||
| 6291 | ||||
| 6292 | // // rearrange icons to fit size | |||
| 6293 | // { | |||
| 6294 | // int borderX = 16; | |||
| 6295 | // int borderY = 32; | |||
| 6296 | // int bodyW = windowSizeLimitMax.x - windowSizeLimitMin.x; | |||
| 6297 | // int bodyH = windowSizeLimitMax.y - windowSizeLimitMin.y; | |||
| 6298 | // fxFrame->setSize(SDL_Rect{ borderX, borderY, bodyW, bodyH }); | |||
| 6299 | // for ( auto img : frameImages ) | |||
| 6300 | // { | |||
| 6301 | // img->pos.x -= (windowSizeLimitMin.x); | |||
| 6302 | // img->pos.y -= (windowSizeLimitMin.y); | |||
| 6303 | // } | |||
| 6304 | // SDL_Rect automatonHungerFramePos = automatonHungerFrame->getSize(); | |||
| 6305 | // automatonHungerFramePos.x += borderX; | |||
| 6306 | // automatonHungerFramePos.y += borderY; | |||
| 6307 | // automatonHungerFramePos.x -= (windowSizeLimitMin.x); | |||
| 6308 | // automatonHungerFramePos.y -= (windowSizeLimitMin.y); | |||
| 6309 | // automatonHungerFrame->setSize(automatonHungerFramePos); | |||
| 6310 | ||||
| 6311 | // SDL_Rect windowPos{ 0, 0, borderX * 2 + bodyW, borderY + bodyH + 16 }; | |||
| 6312 | // statusEffectFocusedWindow->setSize(windowPos); | |||
| 6313 | // imageResizeToContainer9x9(statusEffectFocusedWindow, SDL_Rect{ 0, 0, windowPos.w, windowPos.h }, | |||
| 6314 | // skillsheetEffectBackgroundImages); | |||
| 6315 | ||||
| 6316 | // auto heading_txt = statusEffectFocusedWindow->findField("heading txt"); | |||
| 6317 | // heading_txt->setSize(SDL_Rect{4, 4, windowPos.w - 4 * 2, 24}); | |||
| 6318 | // } | |||
| 6319 | //} | |||
| 6320 | } | |||
| 6321 | ||||
| 6322 | void StatusEffectQueue_t::animateStatusEffectTooltip(bool showTooltip) | |||
| 6323 | { | |||
| 6324 | if ( !statusEffectTooltipFrame ) | |||
| 6325 | { | |||
| 6326 | return; | |||
| 6327 | } | |||
| 6328 | auto tooltipFrame = statusEffectTooltipFrame; | |||
| 6329 | if ( static_cast<int>(tooltipFrame->getOpacity()) != tooltipOpacitySetpoint ) | |||
| 6330 | { | |||
| 6331 | const real_t fpsScale = getFPSScale(144.0); | |||
| 6332 | if ( tooltipOpacitySetpoint == 0 ) | |||
| 6333 | { | |||
| 6334 | if ( !inputs.getVirtualMouse(player)->draw_cursor ) | |||
| 6335 | { | |||
| 6336 | tooltipOpacityAnimate = 0.0; | |||
| 6337 | } | |||
| 6338 | else | |||
| 6339 | { | |||
| 6340 | if ( ticks - tooltipDeselectedTick > 5 ) | |||
| 6341 | { | |||
| 6342 | real_t factor = 10.0; | |||
| 6343 | real_t setpointDiff = fpsScale * std::max(.05, (tooltipOpacityAnimate)) / (factor); | |||
| 6344 | tooltipOpacityAnimate -= setpointDiff; | |||
| 6345 | tooltipOpacityAnimate = std::max(0.0, tooltipOpacityAnimate); | |||
| 6346 | } | |||
| 6347 | } | |||
| 6348 | } | |||
| 6349 | else | |||
| 6350 | { | |||
| 6351 | real_t setpointDiff = fpsScale * std::max(.05, (1.0 - tooltipOpacityAnimate)) / (1); | |||
| 6352 | tooltipOpacityAnimate += setpointDiff; | |||
| 6353 | tooltipOpacityAnimate = std::min(1.0, tooltipOpacityAnimate); | |||
| 6354 | } | |||
| 6355 | tooltipFrame->setOpacity(tooltipOpacityAnimate * 100); | |||
| 6356 | } | |||
| 6357 | else | |||
| 6358 | { | |||
| 6359 | tooltipFrame->setOpacity(tooltipOpacitySetpoint); | |||
| 6360 | } | |||
| 6361 | ||||
| 6362 | if ( players[player]->hud.hudFrame && players[player]->hud.hudFrame->isDisabled() ) | |||
| 6363 | { | |||
| 6364 | tooltipFrame->setDisabled(true); | |||
| 6365 | } | |||
| 6366 | ||||
| 6367 | if ( tooltipFrame->isDisabled() || !showTooltip ) | |||
| 6368 | { | |||
| 6369 | tooltipShowingEffectID = -1; | |||
| 6370 | tooltipShowingEffectVariable = -1; | |||
| 6371 | return; | |||
| 6372 | } | |||
| 6373 | ||||
| 6374 | tooltipOpacitySetpoint = 0; | |||
| 6375 | tooltipOpacityAnimate = 1.0; | |||
| 6376 | tooltipFrame->setDisabled(false); | |||
| 6377 | tooltipFrame->setOpacity(100.0); | |||
| 6378 | tooltipDeselectedTick = ticks; | |||
| 6379 | } | |||
| 6380 | ||||
| 6381 | bool StatusEffectQueue_t::doStatusEffectTooltip(StatusEffectQueueEntry_t& entry, SDL_Rect pos) | |||
| 6382 | { | |||
| 6383 | auto tooltipFrame = statusEffectTooltipFrame; | |||
| 6384 | if ( !tooltipFrame ) | |||
| 6385 | { | |||
| 6386 | return false; | |||
| 6387 | } | |||
| 6388 | auto tooltipHeader = tooltipFrame->findField("heading txt"); | |||
| 6389 | tooltipHeader->setColor(StatusEffectDefinitions_t::tooltipHeadingColor); | |||
| 6390 | auto tooltipDesc = tooltipFrame->findField("desc txt"); | |||
| 6391 | tooltipDesc->setColor(StatusEffectDefinitions_t::tooltipDescColor); | |||
| 6392 | int fontHeight = Font::get(tooltipDesc->getFont())->height(true); | |||
| 6393 | int tooltipInnerWidth = 200; | |||
| 6394 | ||||
| 6395 | bool refreshTooltip = (tooltipShowingEffectID != entry.effect) || (tooltipShowingEffectVariable != entry.customVariable); | |||
| 6396 | if ( refreshTooltip ) | |||
| 6397 | { | |||
| 6398 | if ( entry.effect >= StatusEffectQueue_t::kSpellEffectOffset ) | |||
| 6399 | { | |||
| 6400 | int effectID = entry.effect - StatusEffectQueue_t::kSpellEffectOffset; | |||
| 6401 | if ( StatusEffectQueue_t::StatusEffectDefinitions_t::sustainedSpellDefinitionExists(effectID) ) | |||
| 6402 | { | |||
| 6403 | auto& definition = StatusEffectQueue_t::StatusEffectDefinitions_t::getSustainedSpell(effectID); | |||
| 6404 | if ( effectID == SPELL_SHADOW_TAG ) | |||
| 6405 | { | |||
| 6406 | int variation = 2; | |||
| 6407 | if ( players[player] && players[player]->entity ) | |||
| 6408 | { | |||
| 6409 | if ( players[player]->entity->creatureShadowTaggedThisUid != 0 | |||
| 6410 | && uidToEntity(players[player]->entity->creatureShadowTaggedThisUid) ) | |||
| 6411 | { | |||
| 6412 | variation = 1; | |||
| 6413 | std::string formatString = definition.getName(variation).c_str(); | |||
| 6414 | char buf[256] = ""; | |||
| 6415 | Entity* tagged = uidToEntity(players[player]->entity->creatureShadowTaggedThisUid); | |||
| 6416 | if ( tagged->behavior == &actMonster ) | |||
| 6417 | { | |||
| 6418 | int type = tagged->getMonsterTypeFromSprite(); | |||
| 6419 | if ( type != NOTHING ) | |||
| 6420 | { | |||
| 6421 | snprintf(buf, sizeof(buf), formatString.c_str(), getMonsterLocalizedName((Monster)type).c_str()); | |||
| 6422 | } | |||
| 6423 | else | |||
| 6424 | { | |||
| 6425 | strcpy(buf, ""); | |||
| 6426 | } | |||
| 6427 | } | |||
| 6428 | else if ( tagged->behavior == &actPlayer ) | |||
| 6429 | { | |||
| 6430 | snprintf(buf, sizeof(buf), formatString.c_str(), stats[tagged->skill[2]]->name); | |||
| 6431 | } | |||
| 6432 | std::string formattedName = buf; | |||
| 6433 | uppercaseString(formattedName); | |||
| 6434 | tooltipHeader->setText(formattedName.c_str()); | |||
| 6435 | } | |||
| 6436 | } | |||
| 6437 | if ( variation == 2 ) | |||
| 6438 | { | |||
| 6439 | std::string newHeader = definition.getName(variation).c_str(); | |||
| 6440 | uppercaseString(newHeader); | |||
| 6441 | tooltipHeader->setText(newHeader.c_str()); | |||
| 6442 | } | |||
| 6443 | tooltipDesc->setText(definition.getDesc(-1).c_str()); // always -1 default desc | |||
| 6444 | tooltipInnerWidth = definition.tooltipWidth; | |||
| 6445 | } | |||
| 6446 | else | |||
| 6447 | { | |||
| 6448 | int variation = -1; | |||
| 6449 | std::string newHeader = definition.getName(variation).c_str(); | |||
| 6450 | uppercaseString(newHeader); | |||
| 6451 | tooltipHeader->setText(newHeader.c_str()); | |||
| 6452 | tooltipDesc->setText(definition.getDesc(variation).c_str()); | |||
| 6453 | tooltipInnerWidth = definition.tooltipWidth; | |||
| 6454 | } | |||
| 6455 | } | |||
| 6456 | } | |||
| 6457 | else | |||
| 6458 | { | |||
| 6459 | int effectID = entry.effect; | |||
| 6460 | if ( StatusEffectQueue_t::StatusEffectDefinitions_t::effectDefinitionExists(effectID) ) | |||
| 6461 | { | |||
| 6462 | auto& definition = StatusEffectQueue_t::StatusEffectDefinitions_t::getEffect(effectID); | |||
| 6463 | int variation = -1; | |||
| 6464 | if ( effectID == EFF_SHAPESHIFT ) | |||
| 6465 | { | |||
| 6466 | if ( players[player] && players[player]->entity ) | |||
| 6467 | { | |||
| 6468 | switch ( players[player]->entity->effectShapeshift ) | |||
| 6469 | { | |||
| 6470 | case RAT: | |||
| 6471 | variation = 0; | |||
| 6472 | break; | |||
| 6473 | case SPIDER: | |||
| 6474 | variation = 1; | |||
| 6475 | break; | |||
| 6476 | case TROLL: | |||
| 6477 | variation = 2; | |||
| 6478 | break; | |||
| 6479 | case CREATURE_IMP: | |||
| 6480 | variation = 3; | |||
| 6481 | break; | |||
| 6482 | default: | |||
| 6483 | break; | |||
| 6484 | } | |||
| 6485 | } | |||
| 6486 | } | |||
| 6487 | else if ( effectID == EFF_VAMPIRICAURA ) | |||
| 6488 | { | |||
| 6489 | bool sustained = false; | |||
| 6490 | for ( node_t* node = channeledSpells[player].first; node != nullptr; node = node->next ) | |||
| 6491 | { | |||
| 6492 | spell_t* spell = (spell_t*)node->element; | |||
| 6493 | if ( spell && spell->ID == SPELL_VAMPIRIC_AURA ) | |||
| 6494 | { | |||
| 6495 | sustained = true; | |||
| 6496 | break; | |||
| 6497 | } | |||
| 6498 | } | |||
| 6499 | if ( sustained ) | |||
| 6500 | { | |||
| 6501 | variation = 1; | |||
| 6502 | } | |||
| 6503 | else | |||
| 6504 | { | |||
| 6505 | variation = 0; | |||
| 6506 | } | |||
| 6507 | } | |||
| 6508 | else if ( effectID == StatusEffectQueue_t::kEffectBread | |||
| 6509 | || effectID == StatusEffectQueue_t::kEffectBloodHunger ) | |||
| 6510 | { | |||
| 6511 | if ( entry.customVariable >= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_OVERSATIATED) ) | |||
| 6512 | { | |||
| 6513 | variation = 0; | |||
| 6514 | } | |||
| 6515 | else if ( entry.customVariable <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_STARVING) ) | |||
| 6516 | { | |||
| 6517 | variation = 3; | |||
| 6518 | } | |||
| 6519 | else if ( entry.customVariable <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_WEAK) ) | |||
| 6520 | { | |||
| 6521 | variation = 2; | |||
| 6522 | } | |||
| 6523 | else if ( entry.customVariable <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_HUNGRY) ) | |||
| 6524 | { | |||
| 6525 | variation = 1; | |||
| 6526 | } | |||
| 6527 | } | |||
| 6528 | else if ( effectID == StatusEffectQueue_t::kEffectAutomatonHunger ) | |||
| 6529 | { | |||
| 6530 | int nameVariation = 1; | |||
| 6531 | int descVariation = 1; | |||
| 6532 | if ( entry.customVariable >= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_AUTOMATON_SUPERHEATED) ) | |||
| 6533 | { | |||
| 6534 | nameVariation = 3; | |||
| 6535 | descVariation = 0; | |||
| 6536 | } | |||
| 6537 | else if ( entry.customVariable <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_AUTOMATON_CRITICAL) ) | |||
| 6538 | { | |||
| 6539 | nameVariation = 5; | |||
| 6540 | if ( svFlags & SV_FLAG_HUNGER ) | |||
| 6541 | { | |||
| 6542 | descVariation = 2; | |||
| 6543 | } | |||
| 6544 | else | |||
| 6545 | { | |||
| 6546 | descVariation = 3; | |||
| 6547 | } | |||
| 6548 | } | |||
| 6549 | else | |||
| 6550 | { | |||
| 6551 | nameVariation = 4; | |||
| 6552 | descVariation = 1; | |||
| 6553 | } | |||
| 6554 | ||||
| 6555 | std::string newHeader = definition.getName(nameVariation).c_str(); | |||
| 6556 | uppercaseString(newHeader); | |||
| 6557 | tooltipHeader->setText(newHeader.c_str()); | |||
| 6558 | tooltipDesc->setText(definition.getDesc(descVariation).c_str()); | |||
| 6559 | tooltipInnerWidth = definition.tooltipWidth; | |||
| 6560 | } | |||
| 6561 | else if ( effectID == StatusEffectQueue_t::kEffectWanted | |||
| 6562 | || effectID == StatusEffectQueue_t::kEffectWantedInShop ) | |||
| 6563 | { | |||
| 6564 | auto& definition2 = StatusEffectQueue_t::StatusEffectDefinitions_t::getEffect(kEffectWanted); | |||
| 6565 | std::string newHeader = definition2.getName(variation).c_str(); | |||
| 6566 | uppercaseString(newHeader); | |||
| 6567 | tooltipHeader->setText(newHeader.c_str()); | |||
| 6568 | tooltipDesc->setText(""); | |||
| 6569 | tooltipInnerWidth = definition.tooltipWidth; | |||
| 6570 | if ( auto h = ShopkeeperPlayerHostility.getPlayerHostility(player) ) | |||
| 6571 | { | |||
| 6572 | char buf[128]; | |||
| 6573 | memset(buf, 0, sizeof(buf)); | |||
| 6574 | snprintf(buf, sizeof(buf), definition.getDesc(0).c_str(), getMonsterLocalizedName(h->playerRace).c_str()); | |||
| 6575 | std::string descStr = buf; | |||
| 6576 | if ( h->wantedLevel == ShopkeeperPlayerHostility.FAILURE_TO_IDENTIFY ) | |||
| 6577 | { | |||
| 6578 | if ( descStr != "" ) { descStr += '\n'; } | |||
| 6579 | descStr += definition.getDesc(4); | |||
| 6580 | } | |||
| 6581 | if ( h->numKills > 0 ) | |||
| 6582 | { | |||
| 6583 | //snprintf(buf, sizeof(buf), definition.getDesc(1).c_str(), h->numKills); | |||
| 6584 | if ( descStr != "" ) { descStr += '\n'; } | |||
| 6585 | //descStr += buf; | |||
| 6586 | descStr += definition.getDesc(1); | |||
| 6587 | } | |||
| 6588 | if ( h->numAggressions > 0 ) | |||
| 6589 | { | |||
| 6590 | //snprintf(buf, sizeof(buf), definition.getDesc(2).c_str(), h->numAggressions); | |||
| 6591 | if ( descStr != "" ) { descStr += '\n'; } | |||
| 6592 | //descStr += buf; | |||
| 6593 | descStr += definition.getDesc(2); | |||
| 6594 | } | |||
| 6595 | if ( h->numAccessories > 0 ) | |||
| 6596 | { | |||
| 6597 | //snprintf(buf, sizeof(buf), definition.getDesc(3).c_str(), h->numAccessories); | |||
| 6598 | if ( descStr != "" ) { descStr += '\n'; } | |||
| 6599 | //descStr += buf; | |||
| 6600 | descStr += definition.getDesc(3); | |||
| 6601 | } | |||
| 6602 | tooltipDesc->setText(descStr.c_str()); | |||
| 6603 | } | |||
| 6604 | } | |||
| 6605 | else if ( effectID == StatusEffectQueue_t::kEffectDisabledHPRegen ) | |||
| 6606 | { | |||
| 6607 | variation = 0; | |||
| 6608 | if ( !(svFlags & SV_FLAG_HUNGER) ) | |||
| 6609 | { | |||
| 6610 | variation = 1; | |||
| 6611 | } | |||
| 6612 | ||||
| 6613 | std::string newHeader = definition.getName(-1).c_str(); | |||
| 6614 | uppercaseString(newHeader); | |||
| 6615 | tooltipHeader->setText(newHeader.c_str()); | |||
| 6616 | tooltipDesc->setText(definition.getDesc(variation).c_str()); | |||
| 6617 | tooltipInnerWidth = definition.tooltipWidth; | |||
| 6618 | } | |||
| 6619 | else if ( effectID == StatusEffectQueue_t::kEffectBountyTarget ) | |||
| 6620 | { | |||
| 6621 | std::string newHeader = definition.getName(1).c_str(); | |||
| 6622 | uppercaseString(newHeader); | |||
| 6623 | tooltipHeader->setText(newHeader.c_str()); | |||
| 6624 | tooltipDesc->setText(definition.getDesc(variation).c_str()); | |||
| 6625 | tooltipInnerWidth = definition.tooltipWidth; | |||
| 6626 | } | |||
| 6627 | ||||
| 6628 | if ( effectID != StatusEffectQueue_t::kEffectAutomatonHunger | |||
| 6629 | && effectID != StatusEffectQueue_t::kEffectWanted | |||
| 6630 | && effectID != StatusEffectQueue_t::kEffectWantedInShop | |||
| 6631 | && effectID != StatusEffectQueue_t::kEffectBountyTarget | |||
| 6632 | && effectID != StatusEffectQueue_t::kEffectDisabledHPRegen ) | |||
| 6633 | { | |||
| 6634 | std::string newHeader = definition.getName(variation).c_str(); | |||
| 6635 | uppercaseString(newHeader); | |||
| 6636 | tooltipHeader->setText(newHeader.c_str()); | |||
| 6637 | tooltipDesc->setText(definition.getDesc(variation).c_str()); | |||
| 6638 | tooltipInnerWidth = definition.tooltipWidth; | |||
| 6639 | } | |||
| 6640 | } | |||
| 6641 | } | |||
| 6642 | } | |||
| 6643 | else | |||
| 6644 | { | |||
| 6645 | if ( entry.effect >= StatusEffectQueue_t::kSpellEffectOffset ) | |||
| 6646 | { | |||
| 6647 | int effectID = entry.effect - StatusEffectQueue_t::kSpellEffectOffset; | |||
| 6648 | if ( StatusEffectQueue_t::StatusEffectDefinitions_t::sustainedSpellDefinitionExists(effectID) ) | |||
| 6649 | { | |||
| 6650 | auto& definition = StatusEffectQueue_t::StatusEffectDefinitions_t::getSustainedSpell(effectID); | |||
| 6651 | tooltipInnerWidth = definition.tooltipWidth; | |||
| 6652 | } | |||
| 6653 | } | |||
| 6654 | else | |||
| 6655 | { | |||
| 6656 | int effectID = entry.effect; | |||
| 6657 | if ( StatusEffectQueue_t::StatusEffectDefinitions_t::effectDefinitionExists(effectID) ) | |||
| 6658 | { | |||
| 6659 | auto& definition = StatusEffectQueue_t::StatusEffectDefinitions_t::getEffect(effectID); | |||
| 6660 | tooltipInnerWidth = definition.tooltipWidth; | |||
| 6661 | } | |||
| 6662 | } | |||
| 6663 | } | |||
| 6664 | ||||
| 6665 | tooltipInnerWidth = std::max(tooltipInnerWidth, (int)tooltipHeader->getTextObject()->getWidth() + (tooltipHeader->getSize().x * 2)); | |||
| 6666 | ||||
| 6667 | const int padx = 16; | |||
| 6668 | const int pady1 = 4; | |||
| 6669 | tooltipHeader->setSize(SDL_Rect{ padx, pady1, tooltipInnerWidth, fontHeight + 4 }); | |||
| 6670 | ||||
| 6671 | auto descPos = tooltipDesc->getSize(); | |||
| 6672 | descPos.w = tooltipInnerWidth; | |||
| 6673 | tooltipDesc->setSize(descPos); | |||
| 6674 | if ( refreshTooltip ) | |||
| 6675 | { | |||
| 6676 | tooltipDesc->reflowTextToFit(0); | |||
| 6677 | } | |||
| 6678 | ||||
| 6679 | const int pady2 = 6; | |||
| 6680 | descPos.x = padx + 4; | |||
| 6681 | descPos.y = tooltipHeader->getSize().y + tooltipHeader->getSize().h + pady2; | |||
| 6682 | descPos.h = tooltipDesc->getNumTextLines() * fontHeight + 4; | |||
| 6683 | tooltipDesc->setSize(descPos); | |||
| 6684 | ||||
| 6685 | tooltipFrame->setDisabled(false); | |||
| 6686 | SDL_Rect tooltipPos; | |||
| 6687 | tooltipPos.w = tooltipInnerWidth + padx * 2; | |||
| 6688 | tooltipPos.h = tooltipHeader->getSize().y + tooltipHeader->getSize().h + pady2 + descPos.h + 8; | |||
| 6689 | tooltipPos.x = pos.x + pos.w; | |||
| 6690 | tooltipPos.y = pos.y - tooltipPos.h - 8; | |||
| 6691 | tooltipPos.y = std::max(0, tooltipPos.y); | |||
| 6692 | tooltipFrame->setSize(tooltipPos); | |||
| 6693 | imageResizeToContainer9x9(tooltipFrame, SDL_Rect{0, 0, tooltipPos.w, tooltipPos.h}, skillsheetEffectBackgroundImages); | |||
| 6694 | tooltipShowingEffectID = entry.effect; | |||
| 6695 | tooltipShowingEffectVariable = entry.customVariable; | |||
| 6696 | return true; | |||
| 6697 | } | |||
| 6698 | ||||
| 6699 | const int StatusEffectQueue_t::kEffectBread = -2; | |||
| 6700 | const int StatusEffectQueue_t::kEffectBloodHunger = -3; | |||
| 6701 | const int StatusEffectQueue_t::kEffectAutomatonHunger = -4; | |||
| 6702 | const int StatusEffectQueue_t::kEffectWanted = -5; | |||
| 6703 | const int StatusEffectQueue_t::kEffectWantedInShop = -6; | |||
| 6704 | const int StatusEffectQueue_t::kEffectBurning = -7; | |||
| 6705 | const int StatusEffectQueue_t::kEffectFreeAction = -8; | |||
| 6706 | const int StatusEffectQueue_t::kEffectLesserWarning = -9; | |||
| 6707 | const int StatusEffectQueue_t::kEffectDisabledHPRegen = -10; | |||
| 6708 | const int StatusEffectQueue_t::kEffectResistBurning = -11; | |||
| 6709 | const int StatusEffectQueue_t::kEffectResistPoison = -12; | |||
| 6710 | const int StatusEffectQueue_t::kEffectSlowDigestion = -13; | |||
| 6711 | const int StatusEffectQueue_t::kEffectStrangulation = -14; | |||
| 6712 | const int StatusEffectQueue_t::kEffectWarning = -15; | |||
| 6713 | const int StatusEffectQueue_t::kEffectWaterBreathing = -16; | |||
| 6714 | const int StatusEffectQueue_t::kEffectConflict = -17; | |||
| 6715 | const int StatusEffectQueue_t::kEffectWaterWalking = -18; | |||
| 6716 | const int StatusEffectQueue_t::kEffectLifesaving = -19; | |||
| 6717 | const int StatusEffectQueue_t::kEffectPush = -20; | |||
| 6718 | const int StatusEffectQueue_t::kEffectSneak = -21; | |||
| 6719 | const int StatusEffectQueue_t::kEffectDrunkGoatman = -22; | |||
| 6720 | const int StatusEffectQueue_t::kEffectBountyTarget = -23; | |||
| 6721 | const int StatusEffectQueue_t::kEffectInspiration = -24; | |||
| 6722 | const int StatusEffectQueue_t::kEffectRetaliation = -25; | |||
| 6723 | const int StatusEffectQueue_t::kSpellEffectOffset = 10000; | |||
| 6724 | ||||
| 6725 | Frame* StatusEffectQueue_t::getStatusEffectFrame() | |||
| 6726 | { | |||
| 6727 | return statusEffectFrame; | |||
| 6728 | } | |||
| 6729 | ||||
| 6730 | void StatusEffectQueue_t::handleNavigation(std::map<int, StatusEffectQueueEntry_t*>& grid, | |||
| 6731 | bool& tooltipShowing, const bool hungerEffectInEffectQueue) | |||
| 6732 | { | |||
| 6733 | if ( !inputs.hasController(player) | |||
| 6734 | || inputs.getVirtualMouse(player)->draw_cursor | |||
| 6735 | || players[player]->shootmode ) | |||
| 6736 | { | |||
| 6737 | return; | |||
| 6738 | } | |||
| 6739 | ||||
| 6740 | if ( players[player]->GUI.activeModule != Player::GUI_t::MODULE_STATUS_EFFECTS | |||
| 6741 | && players[player]->GUI.activeModule == Player::GUI_t::MODULE_INVENTORY ) | |||
| 6742 | { | |||
| 6743 | ||||
| 6744 | } | |||
| 6745 | ||||
| 6746 | if ( players[player]->GUI.activeModule != Player::GUI_t::MODULE_STATUS_EFFECTS ) | |||
| 6747 | { | |||
| 6748 | return; | |||
| 6749 | } | |||
| 6750 | ||||
| 6751 | if ( effectQueue.size() == 0 ) | |||
| 6752 | { | |||
| 6753 | return; | |||
| 6754 | } | |||
| 6755 | ||||
| 6756 | ||||
| 6757 | StatusEffectQueueEntry_t::Dir_t inputDirection = StatusEffectQueueEntry_t::Dir_t::NONE; | |||
| 6758 | if ( Input::inputs[player].consumeBinaryToggle("InventoryMoveUp") ) | |||
| 6759 | { | |||
| 6760 | inputDirection = StatusEffectQueueEntry_t::Dir_t::UP; | |||
| 6761 | } | |||
| 6762 | if ( Input::inputs[player].consumeBinaryToggle("InventoryMoveUpAnalog") ) | |||
| 6763 | { | |||
| 6764 | inputDirection = StatusEffectQueueEntry_t::Dir_t::UP; | |||
| 6765 | } | |||
| 6766 | if ( Input::inputs[player].consumeBinaryToggle("InventoryMoveDown") ) | |||
| 6767 | { | |||
| 6768 | inputDirection = StatusEffectQueueEntry_t::Dir_t::DOWN; | |||
| 6769 | } | |||
| 6770 | if ( Input::inputs[player].consumeBinaryToggle("InventoryMoveDownAnalog") ) | |||
| 6771 | { | |||
| 6772 | inputDirection = StatusEffectQueueEntry_t::Dir_t::DOWN; | |||
| 6773 | } | |||
| 6774 | if ( Input::inputs[player].consumeBinaryToggle("InventoryMoveLeft") ) | |||
| 6775 | { | |||
| 6776 | inputDirection = StatusEffectQueueEntry_t::Dir_t::LEFT; | |||
| 6777 | } | |||
| 6778 | if ( Input::inputs[player].consumeBinaryToggle("InventoryMoveLeftAnalog") ) | |||
| 6779 | { | |||
| 6780 | inputDirection = StatusEffectQueueEntry_t::Dir_t::LEFT; | |||
| 6781 | } | |||
| 6782 | if ( Input::inputs[player].consumeBinaryToggle("InventoryMoveRight") ) | |||
| 6783 | { | |||
| 6784 | inputDirection = StatusEffectQueueEntry_t::Dir_t::RIGHT; | |||
| 6785 | } | |||
| 6786 | if ( Input::inputs[player].consumeBinaryToggle("InventoryMoveRightAnalog") ) | |||
| 6787 | { | |||
| 6788 | inputDirection = StatusEffectQueueEntry_t::Dir_t::RIGHT; | |||
| 6789 | } | |||
| 6790 | ||||
| 6791 | selectedElement = std::max(0, selectedElement); | |||
| 6792 | selectedElement = std::min(selectedElement, (int)(effectQueue.size() - 1)); | |||
| 6793 | ||||
| 6794 | StatusEffectQueueEntry_t* selectedEntry = nullptr; | |||
| 6795 | ||||
| 6796 | int miny = 10; | |||
| 6797 | int maxy = 0; | |||
| 6798 | std::vector<int>minx; | |||
| 6799 | std::vector<int>maxx; | |||
| 6800 | for ( int i = 0; i < 32; ++i ) | |||
| 6801 | { | |||
| 6802 | maxx.push_back(0); | |||
| 6803 | minx.push_back(32); | |||
| 6804 | } | |||
| 6805 | for ( auto& slot : grid ) | |||
| 6806 | { | |||
| 6807 | int x = slot.first % 10000; | |||
| 6808 | int y = slot.first / 10000; | |||
| 6809 | ||||
| 6810 | miny = std::min(y, miny); | |||
| 6811 | maxy = std::max(y, maxy); | |||
| 6812 | minx[y] = std::min(x, minx[y]); | |||
| 6813 | maxx[y] = std::max(x, maxx[y]); | |||
| 6814 | } | |||
| 6815 | ||||
| 6816 | // clear navigation graph | |||
| 6817 | for ( auto& q : effectQueue ) | |||
| 6818 | { | |||
| 6819 | q.navigation.clear(); | |||
| 6820 | } | |||
| 6821 | ||||
| 6822 | for ( auto& slot : grid ) | |||
| 6823 | { | |||
| 6824 | int x = slot.first % 10000; | |||
| 6825 | int y = slot.first / 10000; | |||
| 6826 | ||||
| 6827 | if ( slot.second->index == (size_t)selectedElement ) | |||
| 6828 | { | |||
| 6829 | selectedEntry = slot.second; | |||
| 6830 | } | |||
| 6831 | ||||
| 6832 | if ( grid.find((x + 1) + y * 10000) != grid.end() ) | |||
| 6833 | { | |||
| 6834 | auto dest = grid[(x + 1) + y * 10000]; | |||
| 6835 | slot.second->navigation[StatusEffectQueueEntry_t::Dir_t::RIGHT] = dest->index; | |||
| 6836 | } | |||
| 6837 | else | |||
| 6838 | { | |||
| 6839 | if ( hungerEffectInEffectQueue ) | |||
| 6840 | { | |||
| 6841 | auto dest = grid[0 + 0 * 10000]; | |||
| 6842 | slot.second->navigation[StatusEffectQueueEntry_t::Dir_t::RIGHT] = dest->index; | |||
| 6843 | } | |||
| 6844 | else | |||
| 6845 | { | |||
| 6846 | auto dest = grid[(minx[y]) + y * 10000]; | |||
| 6847 | slot.second->navigation[StatusEffectQueueEntry_t::Dir_t::RIGHT] = dest->index; | |||
| 6848 | } | |||
| 6849 | } | |||
| 6850 | if ( grid.find((x - 1) + y * 10000) != grid.end() ) | |||
| 6851 | { | |||
| 6852 | auto dest = grid[(x - 1) + y * 10000]; | |||
| 6853 | slot.second->navigation[StatusEffectQueueEntry_t::Dir_t::LEFT] = dest->index; | |||
| 6854 | } | |||
| 6855 | else | |||
| 6856 | { | |||
| 6857 | if ( hungerEffectInEffectQueue && !(x == 0 && y == 0) ) | |||
| 6858 | { | |||
| 6859 | auto dest = grid[0 + 0 * 10000]; | |||
| 6860 | slot.second->navigation[StatusEffectQueueEntry_t::Dir_t::LEFT] = dest->index; | |||
| 6861 | } | |||
| 6862 | else | |||
| 6863 | { | |||
| 6864 | auto dest = grid[maxx[y] + y * 10000]; | |||
| 6865 | slot.second->navigation[StatusEffectQueueEntry_t::Dir_t::LEFT] = dest->index; | |||
| 6866 | } | |||
| 6867 | } | |||
| 6868 | if ( grid.find(x + (y + 1) * 10000) != grid.end() ) | |||
| 6869 | { | |||
| 6870 | auto dest = grid[x + (y + 1) * 10000]; | |||
| 6871 | slot.second->navigation[StatusEffectQueueEntry_t::Dir_t::UP] = dest->index; | |||
| 6872 | } | |||
| 6873 | else | |||
| 6874 | { | |||
| 6875 | int destx = std::min(std::max(x, minx[0]), maxx[0]); | |||
| 6876 | auto dest = grid[destx + (0) * 10000]; | |||
| 6877 | slot.second->navigation[StatusEffectQueueEntry_t::Dir_t::UP] = dest->index; | |||
| 6878 | } | |||
| 6879 | if ( grid.find(x + (y - 1) * 10000) != grid.end() ) | |||
| 6880 | { | |||
| 6881 | auto dest = grid[x + (y - 1) * 10000]; | |||
| 6882 | slot.second->navigation[StatusEffectQueueEntry_t::Dir_t::DOWN] = dest->index; | |||
| 6883 | } | |||
| 6884 | else | |||
| 6885 | { | |||
| 6886 | int desty = maxy; | |||
| 6887 | while ( desty > 0 ) | |||
| 6888 | { | |||
| 6889 | if ( grid.find(x + (desty) * 10000) != grid.end() ) | |||
| 6890 | { | |||
| 6891 | auto dest = grid[x + (desty) * 10000]; | |||
| 6892 | slot.second->navigation[StatusEffectQueueEntry_t::Dir_t::DOWN] = dest->index; | |||
| 6893 | break; | |||
| 6894 | } | |||
| 6895 | --desty; | |||
| 6896 | } | |||
| 6897 | } | |||
| 6898 | } | |||
| 6899 | ||||
| 6900 | if ( selectedEntry && inputDirection != StatusEffectQueueEntry_t::Dir_t::NONE ) | |||
| 6901 | { | |||
| 6902 | auto findIndex = selectedEntry->navigation.find(inputDirection); | |||
| 6903 | if ( findIndex != selectedEntry->navigation.end() ) | |||
| 6904 | { | |||
| 6905 | selectedElement = (*findIndex).second; | |||
| 6906 | Player::soundMovement(); | |||
| 6907 | } | |||
| 6908 | } | |||
| 6909 | ||||
| 6910 | auto innerFrame = statusEffectFrame->findFrame("effects"); | |||
| 6911 | auto& frameImages = innerFrame->getImages(); | |||
| 6912 | auto frameImagesIterator = frameImages.begin(); | |||
| 6913 | for ( auto it = effectQueue.rbegin(); it != effectQueue.rend(); ) | |||
| 6914 | { | |||
| 6915 | auto& q = (*it); | |||
| 6916 | ||||
| 6917 | Frame::image_t* frameImg = nullptr; | |||
| 6918 | if ( frameImagesIterator != frameImages.end() ) | |||
| 6919 | { | |||
| 6920 | frameImg = *frameImagesIterator; | |||
| 6921 | } | |||
| 6922 | ||||
| 6923 | if ( q.index == selectedElement ) | |||
| 6924 | { | |||
| 6925 | SDL_Rect size = statusEffectFrame->getAbsoluteSize(); | |||
| 6926 | int mouseDetectionPadding = 2; | |||
| 6927 | ||||
| 6928 | SDL_Rect frameImgPos = frameImg->pos; | |||
| 6929 | bool oldDisabled = frameImg->disabled; | |||
| 6930 | updateEntryImage(q, frameImg); | |||
| 6931 | frameImg->disabled = oldDisabled; | |||
| 6932 | frameImgPos.x = q.animateSetpointX; | |||
| 6933 | frameImgPos.y = q.animateSetpointY; | |||
| 6934 | ||||
| 6935 | size.x += frameImgPos.x - (mouseDetectionPadding); | |||
| 6936 | size.y += frameImgPos.y - (mouseDetectionPadding); | |||
| 6937 | size.w = frameImgPos.w + (mouseDetectionPadding * 2); | |||
| 6938 | size.h = frameImgPos.h + (mouseDetectionPadding * 2); | |||
| 6939 | tooltipShowing = doStatusEffectTooltip(q, size); | |||
| 6940 | players[player]->hud.setCursorDisabled(false); | |||
| 6941 | ||||
| 6942 | // make sure to adjust absolute size to camera viewport | |||
| 6943 | size.x -= players[player]->camera_virtualx1(); | |||
| 6944 | size.y -= players[player]->camera_virtualy1(); | |||
| 6945 | ||||
| 6946 | players[player]->hud.updateCursorAnimation(size.x - 1 + mouseDetectionPadding, size.y - 1 + mouseDetectionPadding, | |||
| 6947 | frameImgPos.w, frameImgPos.h, inputs.getVirtualMouse(player)->draw_cursor); | |||
| 6948 | break; | |||
| 6949 | } | |||
| 6950 | ||||
| 6951 | ++it; | |||
| 6952 | if ( frameImagesIterator != frameImages.end() ) | |||
| 6953 | { | |||
| 6954 | ++frameImagesIterator; | |||
| 6955 | } | |||
| 6956 | } | |||
| 6957 | } | |||
| 6958 | ||||
| 6959 | const bool kAllowGhostStatusEffects = false; | |||
| 6960 | ||||
| 6961 | void StatusEffectQueue_t::updateAllQueuedEffects() | |||
| 6962 | { | |||
| 6963 | bool effectsEnabled = true; | |||
| 6964 | if ( !players[player]->entity && ((multiplayer == SINGLE0 && splitscreen) || multiplayer != SINGLE0) ) | |||
| 6965 | { | |||
| 6966 | effectsEnabled = false; | |||
| 6967 | resetQueue(); | |||
| 6968 | } | |||
| 6969 | if ( players[player]->ghost.isActive() && !kAllowGhostStatusEffects ) | |||
| 6970 | { | |||
| 6971 | effectsEnabled = false; | |||
| 6972 | resetQueue(); | |||
| 6973 | } | |||
| 6974 | ||||
| 6975 | std::unordered_set<int> effectSet; | |||
| 6976 | for ( auto it = effectQueue.rbegin(); it != effectQueue.rend(); ++it ) | |||
| 6977 | { | |||
| 6978 | effectSet.insert((*it).effect); | |||
| 6979 | } | |||
| 6980 | ||||
| 6981 | std::vector<int> effectsToSkipAnimThisFrame; | |||
| 6982 | std::set<int> effectsToSkipAnim; | |||
| 6983 | std::unordered_set<int> spellsActive; | |||
| 6984 | int count = 0; //This is just for debugging purposes. | |||
| 6985 | for ( node_t* node = channeledSpells[player].first; node && effectsEnabled; node = node->next, count++ ) | |||
| 6986 | { | |||
| 6987 | spell_t* spell = (spell_t*)node->element; | |||
| 6988 | if ( !spell ) | |||
| 6989 | { | |||
| 6990 | break; | |||
| 6991 | } | |||
| 6992 | spellsActive.insert(spell->ID); | |||
| 6993 | if ( StatusEffectDefinitions_t::sustainedSpellDefinitionExists(spell->ID) ) | |||
| 6994 | { | |||
| 6995 | if ( StatusEffectDefinitions_t::getSustainedSpell(spell->ID).effect_id == -1 ) | |||
| 6996 | { | |||
| 6997 | // unique sustained effect | |||
| 6998 | int effectID = spell->ID + kSpellEffectOffset; | |||
| 6999 | if ( effectSet.find(effectID) == effectSet.end() ) | |||
| 7000 | { | |||
| 7001 | insertEffect(-1, spell->ID); | |||
| 7002 | } | |||
| 7003 | } | |||
| 7004 | } | |||
| 7005 | } | |||
| 7006 | ||||
| 7007 | for ( auto& eff : effectSet ) | |||
| 7008 | { | |||
| 7009 | if ( eff >= kSpellEffectOffset && (eff - kSpellEffectOffset) == SPELL_SHADOW_TAG ) | |||
| 7010 | { | |||
| 7011 | if ( players[player] && players[player]->entity | |||
| 7012 | && players[player]->entity->creatureShadowTaggedThisUid != 0 | |||
| 7013 | && uidToEntity(players[player]->entity->creatureShadowTaggedThisUid) ) | |||
| 7014 | { | |||
| 7015 | // shadow tag still active, check uid | |||
| 7016 | for ( auto it = effectQueue.rbegin(); it != effectQueue.rend(); ++it ) | |||
| 7017 | { | |||
| 7018 | if ( (*it).effect == kSpellEffectOffset + SPELL_SHADOW_TAG ) | |||
| 7019 | { | |||
| 7020 | if ( (*it).customVariable != players[player]->entity->creatureShadowTaggedThisUid ) | |||
| 7021 | { | |||
| 7022 | deleteEffect(eff); | |||
| 7023 | break; | |||
| 7024 | } | |||
| 7025 | } | |||
| 7026 | } | |||
| 7027 | } | |||
| 7028 | else | |||
| 7029 | { | |||
| 7030 | deleteEffect(eff); | |||
| 7031 | } | |||
| 7032 | } | |||
| 7033 | else if ( eff >= kSpellEffectOffset && spellsActive.find(eff - kSpellEffectOffset) == spellsActive.end() ) | |||
| 7034 | { | |||
| 7035 | // effect has expired. | |||
| 7036 | deleteEffect(eff); | |||
| 7037 | } | |||
| 7038 | } | |||
| 7039 | ||||
| 7040 | for ( int i = 0; i <= NUMEFFECTS && effectsEnabled; ++i ) | |||
| 7041 | { | |||
| 7042 | if ( i == NUMEFFECTS ) | |||
| 7043 | { | |||
| 7044 | if ( players[player] && players[player]->entity ) | |||
| 7045 | { | |||
| 7046 | if ( players[player]->entity->creatureShadowTaggedThisUid != 0 | |||
| 7047 | && uidToEntity(players[player]->entity->creatureShadowTaggedThisUid) ) | |||
| 7048 | { | |||
| 7049 | if ( insertEffect(-1, SPELL_SHADOW_TAG) ) | |||
| 7050 | { | |||
| 7051 | effectQueue.back().customVariable = players[player]->entity->creatureShadowTaggedThisUid; | |||
| 7052 | notificationQueue.back().customVariable = players[player]->entity->creatureShadowTaggedThisUid; | |||
| 7053 | } | |||
| 7054 | } | |||
| 7055 | } | |||
| 7056 | } | |||
| 7057 | else | |||
| 7058 | { | |||
| 7059 | bool skipAnim = false; | |||
| 7060 | bool effectActive = stats[player]->EFFECTS[i]; | |||
| 7061 | if ( i == EFF_LEVITATING && !effectActive ) | |||
| 7062 | { | |||
| 7063 | bool tmp = stats[player]->EFFECTS[EFF_FLUTTER]; | |||
| 7064 | stats[player]->EFFECTS[EFF_FLUTTER] = false; | |||
| 7065 | effectActive = isLevitating(stats[player]); | |||
| 7066 | stats[player]->EFFECTS[EFF_FLUTTER] = tmp; | |||
| 7067 | } | |||
| 7068 | else if ( i == EFF_MAGICREFLECT && !effectActive ) | |||
| 7069 | { | |||
| 7070 | if ( stats[player]->amulet ) | |||
| 7071 | { | |||
| 7072 | if ( stats[player]->amulet->type == AMULET_MAGICREFLECTION ) | |||
| 7073 | { | |||
| 7074 | effectActive = true; | |||
| 7075 | } | |||
| 7076 | } | |||
| 7077 | if ( stats[player]->cloak ) | |||
| 7078 | { | |||
| 7079 | if ( stats[player]->cloak->type == CLOAK_MAGICREFLECTION ) | |||
| 7080 | { | |||
| 7081 | effectActive = true; | |||
| 7082 | } | |||
| 7083 | } | |||
| 7084 | } | |||
| 7085 | else if ( i == EFF_INVISIBLE && !effectActive && players[player]->entity ) | |||
| 7086 | { | |||
| 7087 | bool oldSneaking = stats[player]->sneaking; | |||
| 7088 | stats[player]->sneaking = false; | |||
| 7089 | bool activeWithoutSneak = players[player]->entity->isInvisible(); | |||
| 7090 | stats[player]->sneaking = oldSneaking; | |||
| 7091 | effectActive = players[player]->entity->isInvisible(); | |||
| 7092 | if ( !activeWithoutSneak ) | |||
| 7093 | { | |||
| 7094 | skipAnim = true; | |||
| 7095 | effectsToSkipAnim.insert(i); | |||
| 7096 | } | |||
| 7097 | } | |||
| 7098 | else if ( i == EFF_TELEPATH ) | |||
| 7099 | { | |||
| 7100 | skipAnim = true; | |||
| 7101 | effectsToSkipAnim.insert(i); | |||
| 7102 | } | |||
| 7103 | else if ( i == EFF_BLIND ) | |||
| 7104 | { | |||
| 7105 | if ( stats[player]->mask && stats[player]->mask->type == TOOL_BLINDFOLD_TELEPATHY ) | |||
| 7106 | { | |||
| 7107 | skipAnim = true; | |||
| 7108 | effectsToSkipAnim.insert(i); | |||
| 7109 | } | |||
| 7110 | } | |||
| 7111 | else if ( i == EFF_DRUNK && stats[player]->type == GOATMAN ) | |||
| 7112 | { | |||
| 7113 | effectActive = false; | |||
| 7114 | } | |||
| 7115 | ||||
| 7116 | if ( !players[player]->entity ) | |||
| 7117 | { | |||
| 7118 | skipAnim = true; | |||
| 7119 | } | |||
| 7120 | ||||
| 7121 | if ( effectActive ) | |||
| 7122 | { | |||
| 7123 | if ( effectSet.find(i) == effectSet.end() ) | |||
| 7124 | { | |||
| 7125 | if ( i == EFF_SHAPESHIFT ) | |||
| 7126 | { | |||
| 7127 | if ( players[player] && players[player]->entity ) | |||
| 7128 | { | |||
| 7129 | insertEffect(i, -1); | |||
| 7130 | } | |||
| 7131 | } | |||
| 7132 | else | |||
| 7133 | { | |||
| 7134 | insertEffect(i, -1); | |||
| 7135 | } | |||
| 7136 | if ( skipAnim ) | |||
| 7137 | { | |||
| 7138 | effectsToSkipAnimThisFrame.push_back(i); | |||
| 7139 | } | |||
| 7140 | } | |||
| 7141 | else if ( i == EFF_SHAPESHIFT ) | |||
| 7142 | { | |||
| 7143 | if ( !players[player] || !players[player]->entity ) | |||
| 7144 | { | |||
| 7145 | deleteEffect(i); | |||
| 7146 | } | |||
| 7147 | } | |||
| 7148 | } | |||
| 7149 | else | |||
| 7150 | { | |||
| 7151 | if ( effectSet.find(i) != effectSet.end() ) | |||
| 7152 | { | |||
| 7153 | deleteEffect(i); | |||
| 7154 | } | |||
| 7155 | } | |||
| 7156 | } | |||
| 7157 | } | |||
| 7158 | ||||
| 7159 | auto wantedLevel = ShopkeeperPlayerHostility.getWantedLevel(player); | |||
| 7160 | bool wantedOutsideOfShop = false; | |||
| 7161 | bool wantedInsideShop = false; | |||
| 7162 | bool inshop = false; | |||
| 7163 | ||||
| 7164 | std::map<int, bool> miscEffects; | |||
| 7165 | for ( int i = kEffectBurning; i >= kEffectRetaliation; --i ) | |||
| 7166 | { | |||
| 7167 | miscEffects[i] = false; | |||
| 7168 | } | |||
| 7169 | if ( players[player] && players[player]->ghost.isActive() && kAllowGhostStatusEffects ) | |||
| 7170 | { | |||
| 7171 | if ( players[player]->ghost.my->skill[3] == 1 ) // ghost sneaking | |||
| 7172 | { | |||
| 7173 | miscEffects[kEffectSneak] = true; | |||
| 7174 | } | |||
| 7175 | } | |||
| 7176 | if ( players[player] && players[player]->entity ) | |||
| 7177 | { | |||
| 7178 | if ( players[player]->entity->flags[BURNING9] ) | |||
| 7179 | { | |||
| 7180 | miscEffects[kEffectBurning] = true; | |||
| 7181 | } | |||
| 7182 | if ( !(svFlags & SV_FLAG_HUNGER) ) | |||
| 7183 | { | |||
| 7184 | miscEffects[kEffectDisabledHPRegen] = true; | |||
| 7185 | } | |||
| 7186 | if ( stats[player] ) | |||
| 7187 | { | |||
| 7188 | bool cursedItemIsBuff = shouldInvertEquipmentBeatitude(stats[player]); | |||
| 7189 | if ( ((stats[player]->mask && stats[player]->mask->type == TOOL_BLINDFOLD_FOCUS) | |||
| 7190 | || (stats[player]->type == GOATMAN && stats[player]->EFFECTS[EFF_DRUNK])) ) | |||
| 7191 | { | |||
| 7192 | miscEffects[kEffectFreeAction] = true; | |||
| 7193 | } | |||
| 7194 | if ( stats[player]->type == GOATMAN && stats[player]->EFFECTS[EFF_DRUNK] ) | |||
| 7195 | { | |||
| 7196 | miscEffects[kEffectDrunkGoatman] = true; | |||
| 7197 | } | |||
| 7198 | if ( stats[player]->helmet && stats[player]->helmet->type == HAT_BOUNTYHUNTER ) | |||
| 7199 | { | |||
| 7200 | for ( auto target : achievementObserver.playerAchievements[player].bountyTargets ) | |||
| 7201 | { | |||
| 7202 | if ( uidToEntity(target) ) | |||
| 7203 | { | |||
| 7204 | miscEffects[kEffectBountyTarget] = true; | |||
| 7205 | break; | |||
| 7206 | } | |||
| 7207 | } | |||
| 7208 | } | |||
| 7209 | if ( stats[player]->mask && stats[player]->mask->type == MASK_MOUTHKNIFE ) | |||
| 7210 | { | |||
| 7211 | miscEffects[kEffectRetaliation] = true; | |||
| 7212 | } | |||
| 7213 | if ( stats[player]->helmet && | |||
| 7214 | (stats[player]->helmet->type == HAT_LAURELS | |||
| 7215 | || stats[player]->helmet->type == HAT_TURBAN | |||
| 7216 | || stats[player]->helmet->type == HAT_CROWN) ) | |||
| 7217 | { | |||
| 7218 | miscEffects[kEffectInspiration] = true; | |||
| 7219 | } | |||
| 7220 | if ( stats[player]->shoes && stats[player]->shoes->type == ARTIFACT_BOOTS ) | |||
| 7221 | { | |||
| 7222 | miscEffects[kEffectLesserWarning] = true; | |||
| 7223 | } | |||
| 7224 | if ( stats[player]->breastplate && stats[player]->breastplate->type == VAMPIRE_DOUBLET ) | |||
| 7225 | { | |||
| 7226 | if ( (svFlags & SV_FLAG_HUNGER) ) | |||
| 7227 | { | |||
| 7228 | miscEffects[kEffectDisabledHPRegen] = true; | |||
| 7229 | } | |||
| 7230 | } | |||
| 7231 | if ( stats[player]->breastplate && stats[player]->breastplate->type == MACHINIST_APRON ) | |||
| 7232 | { | |||
| 7233 | miscEffects[kEffectResistBurning] = true; | |||
| 7234 | } | |||
| 7235 | if ( stats[player]->amulet && stats[player]->amulet->type == AMULET_POISONRESISTANCE ) | |||
| 7236 | { | |||
| 7237 | miscEffects[kEffectResistPoison] = true; | |||
| 7238 | } | |||
| 7239 | if ( stats[player]->ring && stats[player]->ring->type == RING_SLOWDIGESTION | |||
| 7240 | && (stats[player]->ring->beatitude >= 0 || cursedItemIsBuff) ) | |||
| 7241 | { | |||
| 7242 | if ( (svFlags & SV_FLAG_HUNGER) ) | |||
| 7243 | { | |||
| 7244 | miscEffects[kEffectSlowDigestion] = true; | |||
| 7245 | } | |||
| 7246 | } | |||
| 7247 | if ( stats[player]->amulet && stats[player]->amulet->type == AMULET_STRANGULATION | |||
| 7248 | && stats[player]->type != SKELETON ) | |||
| 7249 | { | |||
| 7250 | miscEffects[kEffectStrangulation] = true; | |||
| 7251 | } | |||
| 7252 | if ( stats[player]->amulet && stats[player]->amulet->type == AMULET_WATERBREATHING ) | |||
| 7253 | { | |||
| 7254 | miscEffects[kEffectWaterBreathing] = true; | |||
| 7255 | } | |||
| 7256 | if ( stats[player]->ring && stats[player]->ring->type == RING_WARNING ) | |||
| 7257 | { | |||
| 7258 | miscEffects[kEffectWarning] = true; | |||
| 7259 | } | |||
| 7260 | if ( stats[player]->ring && stats[player]->ring->type == RING_CONFLICT ) | |||
| 7261 | { | |||
| 7262 | miscEffects[kEffectConflict] = true; | |||
| 7263 | } | |||
| 7264 | if ( (stats[player]->ring && stats[player]->ring->type == RING_STRENGTH) | |||
| 7265 | || (stats[player]->gloves && stats[player]->gloves->type == GAUNTLETS_STRENGTH) | |||
| 7266 | || stats[player]->EFFECTS[EFF_POTION_STR] ) | |||
| 7267 | { | |||
| 7268 | miscEffects[kEffectPush] = true; | |||
| 7269 | } | |||
| 7270 | if ( (stats[player]->shoes && stats[player]->shoes->type == IRON_BOOTS_WATERWALKING) | |||
| 7271 | || skillCapstoneUnlocked(player, PRO_SWIMMING) ) | |||
| 7272 | { | |||
| 7273 | miscEffects[kEffectWaterWalking] = true; | |||
| 7274 | } | |||
| 7275 | if ( (stats[player]->amulet && stats[player]->amulet->type == AMULET_LIFESAVING) | |||
| 7276 | || (((stats[player]->playerRace == RACE_SKELETON && stats[player]->appearance == 0) | |||
| 7277 | || stats[player]->type == SKELETON) && stats[player]->MP >= 75) ) | |||
| 7278 | { | |||
| 7279 | miscEffects[kEffectLifesaving] = true; | |||
| 7280 | } | |||
| 7281 | if ( stats[player]->sneaking == 1 && !stats[player]->defending && !skillCapstoneUnlocked(player, PRO_STEALTH) ) | |||
| 7282 | { | |||
| 7283 | miscEffects[kEffectSneak] = true; | |||
| 7284 | } | |||
| 7285 | } | |||
| 7286 | ||||
| 7287 | int playerx = static_cast<int>(players[player]->entity->x) >> 4; | |||
| 7288 | int playery = static_cast<int>(players[player]->entity->y) >> 4; | |||
| 7289 | if ( playerx >= 0 && playerx < map.width && playery >= 0 && playery < map.height ) | |||
| 7290 | { | |||
| 7291 | // if the criminal was inside a shop | |||
| 7292 | if ( shoparea[playery + playerx * map.height] ) | |||
| 7293 | { | |||
| 7294 | inshop = true; | |||
| 7295 | } | |||
| 7296 | } | |||
| 7297 | if ( wantedLevel != ShopkeeperPlayerHostility_t::NO_WANTED_LEVEL ) | |||
| 7298 | { | |||
| 7299 | /*if ( inshop ) // if we want a re-notify while in the shop | |||
| 7300 | { | |||
| 7301 | if ( effectSet.find(kEffectWantedInShop) == effectSet.end() ) | |||
| 7302 | { | |||
| 7303 | insertEffect(kEffectWantedInShop, -1); | |||
| 7304 | } | |||
| 7305 | if ( effectSet.find(kEffectWanted) != effectSet.end() ) | |||
| 7306 | { | |||
| 7307 | deleteEffect(kEffectWanted); | |||
| 7308 | } | |||
| 7309 | } | |||
| 7310 | else*/ | |||
| 7311 | { | |||
| 7312 | if ( effectSet.find(kEffectWantedInShop) != effectSet.end() ) | |||
| 7313 | { | |||
| 7314 | if ( effectSet.find(kEffectWanted) != effectSet.end() ) | |||
| 7315 | { | |||
| 7316 | deleteEffect(kEffectWanted); | |||
| 7317 | } | |||
| 7318 | for ( auto it = effectQueue.begin(); it != effectQueue.end(); ) | |||
| 7319 | { | |||
| 7320 | if ( (*it).effect == kEffectWantedInShop ) | |||
| 7321 | { | |||
| 7322 | (*it).effect = kEffectWanted; | |||
| 7323 | break; | |||
| 7324 | } | |||
| 7325 | ++it; | |||
| 7326 | } | |||
| 7327 | } | |||
| 7328 | else if ( effectSet.find(kEffectWanted) == effectSet.end() ) | |||
| 7329 | { | |||
| 7330 | insertEffect(kEffectWanted, -1); | |||
| 7331 | } | |||
| 7332 | } | |||
| 7333 | } | |||
| 7334 | } | |||
| 7335 | ||||
| 7336 | for ( int i = kEffectBurning; i >= kEffectRetaliation; --i ) | |||
| 7337 | { | |||
| 7338 | if ( miscEffects[i] == false ) | |||
| 7339 | { | |||
| 7340 | if ( effectSet.find(i) != effectSet.end() ) | |||
| 7341 | { | |||
| 7342 | deleteEffect(i); | |||
| 7343 | } | |||
| 7344 | } | |||
| 7345 | else | |||
| 7346 | { | |||
| 7347 | if ( !players[player]->entity ) | |||
| 7348 | { | |||
| 7349 | effectsToSkipAnim.insert(i); | |||
| 7350 | } | |||
| 7351 | if ( i == kEffectSneak ) | |||
| 7352 | { | |||
| 7353 | effectsToSkipAnim.insert(i); | |||
| 7354 | } | |||
| 7355 | if ( effectSet.find(i) == effectSet.end() ) | |||
| 7356 | { | |||
| 7357 | insertEffect(i, -1); | |||
| 7358 | ||||
| 7359 | if ( i == kEffectSneak ) | |||
| 7360 | { | |||
| 7361 | effectsToSkipAnimThisFrame.push_back(i); | |||
| 7362 | } | |||
| 7363 | } | |||
| 7364 | } | |||
| 7365 | } | |||
| 7366 | ||||
| 7367 | if ( wantedLevel == ShopkeeperPlayerHostility_t::NO_WANTED_LEVEL ) | |||
| 7368 | { | |||
| 7369 | if ( effectSet.find(kEffectWanted) != effectSet.end() ) | |||
| 7370 | { | |||
| 7371 | deleteEffect(kEffectWanted); | |||
| 7372 | } | |||
| 7373 | if ( effectSet.find(kEffectWantedInShop) != effectSet.end() ) | |||
| 7374 | { | |||
| 7375 | deleteEffect(kEffectWantedInShop); | |||
| 7376 | } | |||
| 7377 | } | |||
| 7378 | ||||
| 7379 | bool hungerIconActive = (effectSet.find(kEffectBread) != effectSet.end() | |||
| 7380 | || effectSet.find(kEffectBloodHunger) != effectSet.end() | |||
| 7381 | || effectSet.find(kEffectAutomatonHunger) != effectSet.end()); | |||
| 7382 | if ( !players[player]->entity ) | |||
| 7383 | { | |||
| 7384 | if ( effectSet.find(kEffectBread) != effectSet.end() ) | |||
| 7385 | { | |||
| 7386 | effectsToSkipAnimThisFrame.push_back(kEffectBread); | |||
| 7387 | } | |||
| 7388 | if ( effectSet.find(kEffectBloodHunger) != effectSet.end() ) | |||
| 7389 | { | |||
| 7390 | effectsToSkipAnimThisFrame.push_back(kEffectBloodHunger); | |||
| 7391 | } | |||
| 7392 | if ( effectSet.find(kEffectAutomatonHunger) != effectSet.end() ) | |||
| 7393 | { | |||
| 7394 | effectsToSkipAnimThisFrame.push_back(kEffectAutomatonHunger); | |||
| 7395 | } | |||
| 7396 | } | |||
| 7397 | ||||
| 7398 | Frame* statusEffectFrame = getStatusEffectFrame(); | |||
| 7399 | auto automatonHungerFrame = statusEffectFrame->findFrame("automaton hunger notification"); | |||
| 7400 | automatonHungerFrame->setDisabled(true); | |||
| 7401 | auto automatonFlameImg = automatonHungerFrame->findImage("flame"); | |||
| 7402 | ||||
| 7403 | int iconSize = 32; | |||
| 7404 | int movex = splitscreen ? 4 : 0; | |||
| 7405 | if ( hungerIconActive ) | |||
| 7406 | { | |||
| 7407 | if ( effectSet.find(kEffectBread) != effectSet.end() ) | |||
| 7408 | { | |||
| 7409 | movex += 76; | |||
| 7410 | } | |||
| 7411 | else | |||
| 7412 | { | |||
| 7413 | movex += 64; | |||
| 7414 | } | |||
| 7415 | movex += 4; | |||
| 7416 | } | |||
| 7417 | const int startrowx = movex; | |||
| 7418 | int movey = statusEffectFrame->getSize().h - iconSize; | |||
| 7419 | const int spacing = 36; | |||
| 7420 | int numEffectsOnLine = 0; | |||
| 7421 | ||||
| 7422 | for ( auto eff : effectsToSkipAnimThisFrame ) | |||
| 7423 | { | |||
| 7424 | for ( auto& notif : notificationQueue ) | |||
| 7425 | { | |||
| 7426 | if ( notif.effect == eff ) | |||
| 7427 | { | |||
| 7428 | notif.notificationState = StatusEffectQueueEntry_t::STATE_END; | |||
| 7429 | notif.notificationStateInit = StatusEffectQueueEntry_t::STATE_END; | |||
| 7430 | ||||
| 7431 | notif.notificationTargetPosition.x = movex; | |||
| 7432 | ||||
| 7433 | for ( auto& entry : effectQueue ) | |||
| 7434 | { | |||
| 7435 | if ( entry.effect == eff ) | |||
| 7436 | { | |||
| 7437 | entry.animateSetpointX = notif.notificationTargetPosition.x; | |||
| 7438 | entry.animateSetpointY = notif.notificationTargetPosition.y; | |||
| 7439 | entry.animateSetpointW = entry.notificationTargetPosition.w; | |||
| 7440 | entry.animateSetpointH = entry.notificationTargetPosition.h; | |||
| 7441 | ||||
| 7442 | entry.animateStartX = entry.animateSetpointX; | |||
| 7443 | entry.animateStartY = entry.animateSetpointY; | |||
| 7444 | entry.animateStartW = entry.animateSetpointW; | |||
| 7445 | entry.animateStartH = entry.animateSetpointH; | |||
| 7446 | entry.pos.x = entry.animateSetpointX; | |||
| 7447 | entry.pos.y = entry.animateSetpointY; | |||
| 7448 | entry.pos.w = entry.animateSetpointW; | |||
| 7449 | entry.pos.h = entry.animateSetpointH; | |||
| 7450 | ||||
| 7451 | notif.pos = entry.pos; | |||
| 7452 | } | |||
| 7453 | } | |||
| 7454 | } | |||
| 7455 | } | |||
| 7456 | } | |||
| 7457 | ||||
| 7458 | auto notificationFrame = statusEffectFrame->findFrame("notification frame"); | |||
| 7459 | notificationFrame->setDisabled(true); | |||
| 7460 | auto notificationImg = notificationFrame->findImage("notification img"); | |||
| 7461 | notificationImg->disabled = true; | |||
| 7462 | auto notificationTxt = notificationFrame->findField("notification txt"); | |||
| 7463 | notificationTxt->setDisabled(true); | |||
| 7464 | notificationTxt->setFont(StatusEffectDefinitions_t::notificationFont.c_str()); | |||
| 7465 | notificationTxt->setColor(StatusEffectDefinitions_t::notificationTextColor); | |||
| 7466 | if ( notificationQueue.size() >= 1 ) | |||
| 7467 | { | |||
| 7468 | auto& notif = notificationQueue.front(); | |||
| 7469 | notif.animateNotification(player); | |||
| 7470 | updateEntryImage(notif, notificationImg); | |||
| 7471 | if ( notif.notificationState == StatusEffectQueueEntry_t::STATE_2 | |||
| 7472 | || notif.notificationState == StatusEffectQueueEntry_t::STATE_3 ) | |||
| 7473 | { | |||
| 7474 | if ( notif.effect >= kSpellEffectOffset ) | |||
| 7475 | { | |||
| 7476 | int effectID = notif.effect - kSpellEffectOffset; | |||
| 7477 | if ( StatusEffectDefinitions_t::sustainedSpellDefinitionExists(effectID) ) | |||
| 7478 | { | |||
| 7479 | auto& definition = StatusEffectDefinitions_t::getSustainedSpell(effectID); | |||
| 7480 | if ( notif.notificationState == StatusEffectQueueEntry_t::STATE_2 ) | |||
| 7481 | { | |||
| 7482 | int variation = -1; | |||
| 7483 | if ( effectID == SPELL_SHADOW_TAG ) | |||
| 7484 | { | |||
| 7485 | variation = 0; | |||
| 7486 | notificationTxt->setText(""); | |||
| 7487 | if ( players[player] && players[player]->entity ) | |||
| 7488 | { | |||
| 7489 | if ( players[player]->entity->creatureShadowTaggedThisUid != 0 | |||
| 7490 | && uidToEntity(players[player]->entity->creatureShadowTaggedThisUid) ) | |||
| 7491 | { | |||
| 7492 | std::string formatString = definition.getName(variation).c_str(); | |||
| 7493 | char buf[256] = ""; | |||
| 7494 | Entity* tagged = uidToEntity(players[player]->entity->creatureShadowTaggedThisUid); | |||
| 7495 | if ( tagged->behavior == &actMonster ) | |||
| 7496 | { | |||
| 7497 | int type = tagged->getMonsterTypeFromSprite(); | |||
| 7498 | if ( type != NOTHING ) | |||
| 7499 | { | |||
| 7500 | snprintf(buf, sizeof(buf), formatString.c_str(), getMonsterLocalizedName((Monster)type).c_str()); | |||
| 7501 | } | |||
| 7502 | else | |||
| 7503 | { | |||
| 7504 | strcpy(buf, ""); | |||
| 7505 | } | |||
| 7506 | } | |||
| 7507 | else if ( tagged->behavior == &actPlayer ) | |||
| 7508 | { | |||
| 7509 | snprintf(buf, sizeof(buf), formatString.c_str(), stats[tagged->skill[2]]->name); | |||
| 7510 | } | |||
| 7511 | std::string formattedName = buf; | |||
| 7512 | notificationTxt->setText(formattedName.c_str()); | |||
| 7513 | } | |||
| 7514 | } | |||
| 7515 | } | |||
| 7516 | else | |||
| 7517 | { | |||
| 7518 | notificationTxt->setText(definition.getName(variation).c_str()); | |||
| 7519 | } | |||
| 7520 | } | |||
| 7521 | notificationTxt->setDisabled(false); | |||
| 7522 | } | |||
| 7523 | } | |||
| 7524 | else | |||
| 7525 | { | |||
| 7526 | int effectID = notif.effect; | |||
| 7527 | if ( StatusEffectDefinitions_t::effectDefinitionExists(effectID) ) | |||
| 7528 | { | |||
| 7529 | auto& definition = StatusEffectDefinitions_t::getEffect(effectID); | |||
| 7530 | if ( notif.notificationState == StatusEffectQueueEntry_t::STATE_2 ) | |||
| 7531 | { | |||
| 7532 | int variation = -1; | |||
| 7533 | if ( effectID == EFF_SHAPESHIFT ) | |||
| 7534 | { | |||
| 7535 | if ( players[player] && players[player]->entity ) | |||
| 7536 | { | |||
| 7537 | switch ( players[player]->entity->effectShapeshift ) | |||
| 7538 | { | |||
| 7539 | case RAT: | |||
| 7540 | variation = 0; | |||
| 7541 | break; | |||
| 7542 | case SPIDER: | |||
| 7543 | variation = 1; | |||
| 7544 | break; | |||
| 7545 | case TROLL: | |||
| 7546 | variation = 2; | |||
| 7547 | break; | |||
| 7548 | case CREATURE_IMP: | |||
| 7549 | variation = 3; | |||
| 7550 | break; | |||
| 7551 | default: | |||
| 7552 | break; | |||
| 7553 | } | |||
| 7554 | } | |||
| 7555 | } | |||
| 7556 | else if ( effectID == StatusEffectQueue_t::kEffectBread | |||
| 7557 | || effectID == StatusEffectQueue_t::kEffectBloodHunger ) | |||
| 7558 | { | |||
| 7559 | if ( notif.customVariable >= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_OVERSATIATED) ) | |||
| 7560 | { | |||
| 7561 | variation = 0; | |||
| 7562 | } | |||
| 7563 | else if ( notif.customVariable <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_STARVING) ) | |||
| 7564 | { | |||
| 7565 | variation = 3; | |||
| 7566 | } | |||
| 7567 | else if ( notif.customVariable <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_WEAK) ) | |||
| 7568 | { | |||
| 7569 | variation = 2; | |||
| 7570 | } | |||
| 7571 | else if ( notif.customVariable <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_HUNGRY) ) | |||
| 7572 | { | |||
| 7573 | variation = 1; | |||
| 7574 | } | |||
| 7575 | } | |||
| 7576 | else if ( effectID == StatusEffectQueue_t::kEffectAutomatonHunger ) | |||
| 7577 | { | |||
| 7578 | if ( notif.customVariable >= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_AUTOMATON_SUPERHEATED) ) | |||
| 7579 | { | |||
| 7580 | variation = 0; | |||
| 7581 | } | |||
| 7582 | else if ( notif.customVariable <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_AUTOMATON_CRITICAL) ) | |||
| 7583 | { | |||
| 7584 | variation = 2; | |||
| 7585 | } | |||
| 7586 | else | |||
| 7587 | { | |||
| 7588 | variation = 1; | |||
| 7589 | } | |||
| 7590 | } | |||
| 7591 | else if ( effectID == StatusEffectQueue_t::kEffectBountyTarget ) | |||
| 7592 | { | |||
| 7593 | variation = 0; | |||
| 7594 | } | |||
| 7595 | else if ( effectID == EFF_VAMPIRICAURA ) | |||
| 7596 | { | |||
| 7597 | bool sustained = false; | |||
| 7598 | for ( node_t* node = channeledSpells[player].first; node != nullptr; node = node->next ) | |||
| 7599 | { | |||
| 7600 | spell_t* spell = (spell_t*)node->element; | |||
| 7601 | if ( spell && spell->ID == SPELL_VAMPIRIC_AURA ) | |||
| 7602 | { | |||
| 7603 | sustained = true; | |||
| 7604 | break; | |||
| 7605 | } | |||
| 7606 | } | |||
| 7607 | if ( sustained ) | |||
| 7608 | { | |||
| 7609 | variation = 1; | |||
| 7610 | } | |||
| 7611 | else | |||
| 7612 | { | |||
| 7613 | variation = 0; | |||
| 7614 | } | |||
| 7615 | } | |||
| 7616 | notificationTxt->setText(definition.getName(variation).c_str()); | |||
| 7617 | } | |||
| 7618 | if ( notificationImg->path != "" ) | |||
| 7619 | { | |||
| 7620 | notificationTxt->setDisabled(false); | |||
| 7621 | } | |||
| 7622 | } | |||
| 7623 | } | |||
| 7624 | if ( auto textGet = notificationTxt->getTextObject() ) | |||
| 7625 | { | |||
| 7626 | SDL_Rect txtPos; | |||
| 7627 | txtPos.w = textGet->getWidth(); | |||
| 7628 | txtPos.h = textGet->getHeight() * textGet->getNumTextLines() + 4; | |||
| 7629 | ||||
| 7630 | const int movementAmount = getStatusEffectMovementAmount(player); | |||
| 7631 | txtPos.x = (getBaseEffectPosX() - movementAmount - (notif.getStatusEffectLargestScaling(player) - 1.0) * notif.getEffectSpriteNormalWidth() / 2) | |||
| 7632 | + (notif.getEffectSpriteNormalWidth() * notif.getStatusEffectLargestScaling(player)) / 2 - txtPos.w / 2; | |||
| 7633 | txtPos.y = getBaseEffectPosY() - movementAmount - txtPos.h; | |||
| 7634 | notificationTxt->setSize(txtPos); | |||
| 7635 | } | |||
| 7636 | } | |||
| 7637 | if ( notif.notificationState == StatusEffectQueueEntry_t::STATE_END ) | |||
| 7638 | { | |||
| 7639 | notificationQueue.pop_front(); | |||
| 7640 | } | |||
| 7641 | ||||
| 7642 | if ( notif.effect == kEffectAutomatonHunger ) | |||
| 7643 | { | |||
| 7644 | automatonHungerFrame->setDisabled(false); | |||
| 7645 | automatonHungerFrame->setSize(notificationImg->pos); | |||
| 7646 | } | |||
| 7647 | } | |||
| 7648 | ||||
| 7649 | if ( !notificationImg->disabled || !notificationTxt->isDisabled() ) | |||
| 7650 | { | |||
| 7651 | notificationFrame->setDisabled(false); | |||
| 7652 | notificationFrame->setSize(SDL_Rect{ 0, 0, statusEffectFrame->getSize().w, statusEffectFrame->getSize().h }); | |||
| 7653 | } | |||
| 7654 | ||||
| 7655 | ||||
| 7656 | auto innerFrame = statusEffectFrame->findFrame("effects"); | |||
| 7657 | int numFrameImages = innerFrame->getImages().size(); | |||
| 7658 | while ( effectQueue.size() > numFrameImages ) | |||
| 7659 | { | |||
| 7660 | auto img = innerFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "inner img"); | |||
| 7661 | img->disabled = true; | |||
| 7662 | numFrameImages = innerFrame->getImages().size(); | |||
| 7663 | } | |||
| 7664 | while ( effectQueue.size() < numFrameImages ) | |||
| 7665 | { | |||
| 7666 | innerFrame->getImages().erase(innerFrame->getImages().begin()); | |||
| 7667 | numFrameImages = innerFrame->getImages().size(); | |||
| 7668 | } | |||
| 7669 | auto& frameImages = innerFrame->getImages(); | |||
| 7670 | for ( auto img : frameImages ) | |||
| 7671 | { | |||
| 7672 | img->disabled = true; | |||
| 7673 | } | |||
| 7674 | ||||
| 7675 | auto frameImagesIterator = frameImages.begin(); | |||
| 7676 | bool bFrameCapturesMouse = false; | |||
| 7677 | if ( !players[player]->shootmode && inputs.getVirtualMouse(player)->draw_cursor | |||
| 7678 | && !players[player]->skillSheet.bSkillSheetOpen | |||
| 7679 | && !players[player]->bookGUI.bBookOpen | |||
| 7680 | && !players[player]->signGUI.bSignOpen | |||
| 7681 | && !(players[player]->bUseCompactGUIHeight() && !players[player]->hud.statusFxFocusedWindowActive) | |||
| 7682 | && !inputs.getUIInteraction(player)->selectedItem && !players[player]->GUI.isDropdownActive() ) | |||
| 7683 | { | |||
| 7684 | if ( bFrameCapturesMouse = statusEffectFrame->capturesMouse() ) | |||
| 7685 | { | |||
| 7686 | if ( !players[player]->hud.statusFxFocusedWindowActive ) | |||
| 7687 | { | |||
| 7688 | if ( (playerInventoryFrames[player].backpackFrame | |||
| 7689 | && !playerInventoryFrames[player].backpackFrame->isDisabled() | |||
| 7690 | && playerInventoryFrames[player].backpackFrame->capturesMouse()) | |||
| 7691 | || (playerInventoryFrames[player].invSlotsFrame | |||
| 7692 | && playerInventoryFrames[player].invSlotsFrame->capturesMouse()) ) | |||
| 7693 | { | |||
| 7694 | bFrameCapturesMouse = false; | |||
| 7695 | } | |||
| 7696 | } | |||
| 7697 | } | |||
| 7698 | } | |||
| 7699 | bool tooltipShowing = false; | |||
| 7700 | Sint32 mousex = (inputs.getMouse(player, Inputs::X) / (float)xres) * (float)Frame::virtualScreenX; | |||
| 7701 | Sint32 mousey = (inputs.getMouse(player, Inputs::Y) / (float)yres) * (float)Frame::virtualScreenY; | |||
| 7702 | bool lowDurationFlash = !((ticks % 50) - (ticks % 25)); | |||
| 7703 | ||||
| 7704 | if ( bCompactWidth != players[player]->bUseCompactGUIWidth() ) | |||
| 7705 | { | |||
| 7706 | requiresAnimUpdate = true; | |||
| 7707 | } | |||
| 7708 | if ( bCompactHeight != players[player]->bUseCompactGUIHeight() ) | |||
| 7709 | { | |||
| 7710 | requiresAnimUpdate = true; | |||
| 7711 | } | |||
| 7712 | bCompactWidth = players[player]->bUseCompactGUIWidth(); | |||
| 7713 | bCompactHeight = players[player]->bUseCompactGUIHeight(); | |||
| 7714 | effectsPerRow = 4; | |||
| 7715 | if ( bCompactWidth ) | |||
| 7716 | { | |||
| 7717 | effectsPerRow = 3; | |||
| 7718 | } | |||
| 7719 | ||||
| 7720 | int gridx = 1; | |||
| 7721 | int gridy = 0; | |||
| 7722 | std::map<int, StatusEffectQueueEntry_t*> grid; | |||
| 7723 | size_t index = 0; | |||
| 7724 | bool hungerEffectInEffectQueue = false; | |||
| 7725 | bool moduleActive = players[player]->GUI.activeModule == Player::GUI_t::MODULE_STATUS_EFFECTS; | |||
| 7726 | effectsBoundingBox = SDL_Rect{ 0, 0, 0, 0 }; | |||
| 7727 | for ( auto it = effectQueue.rbegin(); it != effectQueue.rend(); ) | |||
| 7728 | { | |||
| 7729 | auto& q = (*it); | |||
| 7730 | ||||
| 7731 | q.index = index; | |||
| 7732 | ++index; | |||
| 7733 | ||||
| 7734 | Frame::image_t* frameImg = nullptr; | |||
| 7735 | if ( frameImagesIterator != frameImages.end() ) | |||
| 7736 | { | |||
| 7737 | frameImg = *frameImagesIterator; | |||
| 7738 | } | |||
| 7739 | ||||
| 7740 | bool existsInNotifications = false; | |||
| 7741 | for ( auto it2 = notificationQueue.begin(); it2 != notificationQueue.end(); ++it2 ) | |||
| 7742 | { | |||
| 7743 | if ( (*it2).effect == q.effect ) | |||
| 7744 | { | |||
| 7745 | existsInNotifications = true; | |||
| 7746 | if ( effectsToSkipAnim.find(q.effect) != effectsToSkipAnim.end() ) | |||
| 7747 | { | |||
| 7748 | updateEntryImage(q, frameImg); | |||
| 7749 | } | |||
| 7750 | break; | |||
| 7751 | } | |||
| 7752 | } | |||
| 7753 | if ( !existsInNotifications ) | |||
| 7754 | { | |||
| 7755 | updateEntryImage(q, frameImg); | |||
| 7756 | ||||
| 7757 | if ( q.effect == kEffectAutomatonHunger ) | |||
| 7758 | { | |||
| 7759 | automatonHungerFrame->setDisabled(false); | |||
| 7760 | automatonHungerFrame->setSize(frameImg->pos); | |||
| 7761 | } | |||
| 7762 | ||||
| 7763 | if ( bFrameCapturesMouse && !tooltipShowing ) | |||
| 7764 | { | |||
| 7765 | SDL_Rect size = statusEffectFrame->getAbsoluteSize(); | |||
| 7766 | int mouseDetectionPadding = 2; | |||
| 7767 | size.x += frameImg->pos.x - (mouseDetectionPadding); | |||
| 7768 | size.y += frameImg->pos.y - (mouseDetectionPadding); | |||
| 7769 | size.w = frameImg->pos.w + (mouseDetectionPadding * 2); | |||
| 7770 | size.h = frameImg->pos.h + (mouseDetectionPadding * 2); | |||
| 7771 | if ( rectContainsPoint(size, mousex, mousey) ) | |||
| 7772 | { | |||
| 7773 | if ( players[player]->GUI.activeModule == Player::GUI_t::MODULE_STATUS_EFFECTS ) | |||
| 7774 | { | |||
| 7775 | tooltipShowing = doStatusEffectTooltip(q, size); | |||
| 7776 | } | |||
| 7777 | players[player]->GUI.activateModule(Player::GUI_t::MODULE_STATUS_EFFECTS); | |||
| 7778 | players[player]->hud.setCursorDisabled(false); | |||
| 7779 | ||||
| 7780 | // make sure to adjust absolute size to camera viewport | |||
| 7781 | size.x -= players[player]->camera_virtualx1(); | |||
| 7782 | size.y -= players[player]->camera_virtualy1(); | |||
| 7783 | ||||
| 7784 | players[player]->hud.updateCursorAnimation(size.x - 1 + mouseDetectionPadding, size.y - 1 + mouseDetectionPadding, | |||
| 7785 | frameImg->pos.w, frameImg->pos.h, inputs.getVirtualMouse(player)->draw_cursor); | |||
| 7786 | } | |||
| 7787 | } | |||
| 7788 | } | |||
| 7789 | int animatePosX = movex; | |||
| 7790 | int animatePosY = movey; | |||
| 7791 | if ( q.effect == kEffectBread || q.effect == kEffectBloodHunger ) | |||
| 7792 | { | |||
| 7793 | animatePosX = 0; | |||
| 7794 | animatePosY = statusEffectFrame->getSize().h - q.getEffectSpriteNormalHeight(); | |||
| 7795 | } | |||
| 7796 | else if ( q.effect == kEffectAutomatonHunger ) | |||
| 7797 | { | |||
| 7798 | animatePosX = 0; | |||
| 7799 | animatePosY = 4 + statusEffectFrame->getSize().h - q.getEffectSpriteNormalHeight(); | |||
| 7800 | } | |||
| 7801 | ||||
| 7802 | effectsBoundingBox.y = std::max(effectsBoundingBox.y, animatePosY + q.getEffectSpriteNormalHeight()); | |||
| 7803 | effectsBoundingBox.w = std::max(effectsBoundingBox.w, animatePosX + q.getEffectSpriteNormalWidth()); | |||
| 7804 | if ( effectsBoundingBox.h == 0 ) | |||
| 7805 | { | |||
| 7806 | effectsBoundingBox.h = animatePosY; | |||
| 7807 | } | |||
| 7808 | else | |||
| 7809 | { | |||
| 7810 | effectsBoundingBox.h = std::min(effectsBoundingBox.h, animatePosY); | |||
| 7811 | } | |||
| 7812 | ||||
| 7813 | // low duration flash | |||
| 7814 | bool effectIsSustained = false; | |||
| 7815 | if ( StatusEffectDefinitions_t::effectDefinitionExists(q.effect) ) | |||
| 7816 | { | |||
| 7817 | auto& definition = StatusEffectDefinitions_t::getEffect(q.effect); | |||
| 7818 | if ( definition.sustainedSpellID >= 0 ) | |||
| 7819 | { | |||
| 7820 | if ( spellsActive.find(definition.sustainedSpellID) != spellsActive.end() ) | |||
| 7821 | { | |||
| 7822 | effectIsSustained = true; | |||
| 7823 | } | |||
| 7824 | } | |||
| 7825 | } | |||
| 7826 | ||||
| 7827 | q.lowDuration = false; | |||
| 7828 | if ( !effectIsSustained && q.effect >= 0 && q.effect < NUMEFFECTS ) | |||
| 7829 | { | |||
| 7830 | bool lowDuration = stats[player]->EFFECTS_TIMERS[q.effect] > 0 && | |||
| 7831 | (stats[player]->EFFECTS_TIMERS[q.effect] < TICKS_PER_SECOND50 * 5); | |||
| 7832 | if ( q.effect == EFF_NAUSEA_PROTECTION ) | |||
| 7833 | { | |||
| 7834 | lowDuration = false; | |||
| 7835 | } | |||
| 7836 | else if ( q.effect == EFF_BLIND && stats[player]->mask | |||
| 7837 | && (stats[player]->mask->type == TOOL_BLINDFOLD | |||
| 7838 | || stats[player]->mask->type == TOOL_BLINDFOLD_FOCUS | |||
| 7839 | || stats[player]->mask->type == TOOL_BLINDFOLD_TELEPATHY) ) | |||
| 7840 | { | |||
| 7841 | lowDuration = false; | |||
| 7842 | } | |||
| 7843 | else if ( q.effect == EFF_TELEPATH && stats[player]->mask | |||
| 7844 | && (stats[player]->mask->type == TOOL_BLINDFOLD_TELEPATHY) ) | |||
| 7845 | { | |||
| 7846 | lowDuration = false; | |||
| 7847 | } | |||
| 7848 | q.lowDuration = lowDuration; | |||
| 7849 | if ( lowDuration && lowDurationFlash ) | |||
| 7850 | { | |||
| 7851 | frameImg->disabled = true; | |||
| 7852 | } | |||
| 7853 | } | |||
| 7854 | else if ( q.effect == kEffectBread || q.effect == kEffectBloodHunger || q.effect == kEffectAutomatonHunger ) | |||
| 7855 | { | |||
| 7856 | if ( q.effect == kEffectAutomatonHunger ) | |||
| 7857 | { | |||
| 7858 | if ( q.customVariable <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_AUTOMATON_CRITICAL) ) | |||
| 7859 | { | |||
| 7860 | q.lowDuration = true; | |||
| 7861 | if ( lowDurationFlash ) | |||
| 7862 | { | |||
| 7863 | frameImg->disabled = true; | |||
| 7864 | automatonHungerFrame->setDisabled(true); | |||
| 7865 | } | |||
| 7866 | } | |||
| 7867 | } | |||
| 7868 | else | |||
| 7869 | { | |||
| 7870 | if ( q.customVariable <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_WEAK) ) | |||
| 7871 | { | |||
| 7872 | q.lowDuration = true; | |||
| 7873 | if ( lowDurationFlash ) | |||
| 7874 | { | |||
| 7875 | frameImg->disabled = true; | |||
| 7876 | } | |||
| 7877 | } | |||
| 7878 | } | |||
| 7879 | } | |||
| 7880 | else if ( q.effect == kEffectBurning ) | |||
| 7881 | { | |||
| 7882 | q.lowDuration = true; | |||
| 7883 | if ( lowDurationFlash ) | |||
| 7884 | { | |||
| 7885 | frameImg->disabled = true; | |||
| 7886 | } | |||
| 7887 | } | |||
| 7888 | else if ( q.effect == kEffectPush ) | |||
| 7889 | { | |||
| 7890 | q.lowDuration = false; | |||
| 7891 | if ( !((stats[player]->ring && stats[player]->ring->type == RING_STRENGTH) | |||
| 7892 | || (stats[player]->gloves && stats[player]->gloves->type == GAUNTLETS_STRENGTH)) ) | |||
| 7893 | { | |||
| 7894 | bool lowDuration = stats[player]->EFFECTS_TIMERS[EFF_POTION_STR] > 0 && | |||
| 7895 | (stats[player]->EFFECTS_TIMERS[EFF_POTION_STR] < TICKS_PER_SECOND50 * 5); | |||
| 7896 | q.lowDuration = lowDuration; | |||
| 7897 | if ( lowDurationFlash && lowDuration ) | |||
| 7898 | { | |||
| 7899 | frameImg->disabled = true; | |||
| 7900 | } | |||
| 7901 | } | |||
| 7902 | } | |||
| 7903 | ||||
| 7904 | if ( requiresAnimUpdate ) | |||
| 7905 | { | |||
| 7906 | q.setAnimatePosition(animatePosX, animatePosY); | |||
| 7907 | } | |||
| 7908 | for ( auto it2 = notificationQueue.begin(); it2 != notificationQueue.end(); ++it2 ) | |||
| 7909 | { | |||
| 7910 | if ( (*it2).effect == q.effect ) | |||
| 7911 | { | |||
| 7912 | (*it2).notificationTargetPosition.x = animatePosX; | |||
| 7913 | (*it2).notificationTargetPosition.y = animatePosY; | |||
| 7914 | break; | |||
| 7915 | } | |||
| 7916 | } | |||
| 7917 | ||||
| 7918 | ++it; | |||
| 7919 | if ( frameImagesIterator != frameImages.end() ) | |||
| 7920 | { | |||
| 7921 | ++frameImagesIterator; | |||
| 7922 | } | |||
| 7923 | ||||
| 7924 | q.animate(); | |||
| 7925 | ||||
| 7926 | if ( q.effect == kEffectBread || q.effect == kEffectBloodHunger || q.effect == kEffectAutomatonHunger ) | |||
| 7927 | { | |||
| 7928 | assert(grid.find(0 + 0 * 10000) == grid.end())(static_cast<void> (0)); | |||
| 7929 | grid[0 + 0 * 10000] = &q; | |||
| 7930 | ||||
| 7931 | hungerEffectInEffectQueue = true; | |||
| 7932 | continue; // don't advance position as this is fixed | |||
| 7933 | } | |||
| 7934 | ||||
| 7935 | assert(grid.find(gridx + gridy * 10000) == grid.end())(static_cast<void> (0)); | |||
| 7936 | grid[gridx + gridy * 10000] = &q; | |||
| 7937 | ||||
| 7938 | ||||
| 7939 | ++gridx; | |||
| 7940 | movex += spacing; | |||
| 7941 | ++numEffectsOnLine; | |||
| 7942 | if ( numEffectsOnLine >= effectsPerRow ) | |||
| 7943 | { | |||
| 7944 | numEffectsOnLine = 0; | |||
| 7945 | movex = startrowx; | |||
| 7946 | movey -= spacing; | |||
| 7947 | gridx = 1; | |||
| 7948 | ++gridy; | |||
| 7949 | } | |||
| 7950 | } | |||
| 7951 | ||||
| 7952 | handleNavigation(grid, tooltipShowing, hungerEffectInEffectQueue); | |||
| 7953 | ||||
| 7954 | if ( stats[player] && stats[player]->type == AUTOMATON && !automatonHungerFrame->isDisabled() ) | |||
| 7955 | { | |||
| 7956 | SDL_Rect automatonHungerFramePos = automatonHungerFrame->getSize(); | |||
| 7957 | SDL_Rect boilerFlamePos = automatonHungerFramePos; | |||
| 7958 | boilerFlamePos.x = 0; | |||
| 7959 | boilerFlamePos.y = 0; | |||
| 7960 | if ( stats[player]->HUNGER > 300 ) | |||
| 7961 | { | |||
| 7962 | if ( stats[player]->HUNGER > 1200 ) | |||
| 7963 | { | |||
| 7964 | automatonFlameImg->path = "images/system/Hunger_boiler_hotfire.png"; | |||
| 7965 | automatonFlameImg->pos = boilerFlamePos; | |||
| 7966 | } | |||
| 7967 | else | |||
| 7968 | { | |||
| 7969 | automatonFlameImg->path = "images/system/Hunger_boiler_fire.png"; | |||
| 7970 | if ( stats[player]->HUNGER > 600 ) | |||
| 7971 | { | |||
| 7972 | automatonFlameImg->pos = boilerFlamePos; | |||
| 7973 | } | |||
| 7974 | else | |||
| 7975 | { | |||
| 7976 | float percent = (stats[player]->HUNGER - 200) / 400.f; // always show a little bit more at the bottom (10-20%) | |||
| 7977 | automatonFlameImg->pos = boilerFlamePos; | |||
| 7978 | int newHeight = boilerFlamePos.h * percent; | |||
| 7979 | int heightDiff = boilerFlamePos.h - newHeight; | |||
| 7980 | automatonFlameImg->pos.y -= heightDiff; | |||
| 7981 | automatonHungerFramePos.y += heightDiff; | |||
| 7982 | automatonHungerFramePos.h -= heightDiff; | |||
| 7983 | automatonHungerFrame->setSize(automatonHungerFramePos); | |||
| 7984 | } | |||
| 7985 | } | |||
| 7986 | } | |||
| 7987 | else | |||
| 7988 | { | |||
| 7989 | automatonHungerFrame->setDisabled(true); | |||
| 7990 | } | |||
| 7991 | } | |||
| 7992 | ||||
| 7993 | animateStatusEffectTooltip(tooltipShowing); | |||
| 7994 | ||||
| 7995 | if ( moduleActive && inputs.getVirtualMouse(player)->draw_cursor ) | |||
| 7996 | { | |||
| 7997 | if ( !tooltipShowing /*&& !players[player]->hud.statusFxFocusedWindowActive*/ ) | |||
| 7998 | { | |||
| 7999 | players[player]->GUI.activateModule(Player::GUI_t::MODULE_NONE); | |||
| 8000 | } | |||
| 8001 | } | |||
| 8002 | ||||
| 8003 | requiresAnimUpdate = false; | |||
| 8004 | } | |||
| 8005 | ||||
| 8006 | void StatusEffectQueue_t::updateEntryImage(StatusEffectQueueEntry_t& entry, Frame::image_t* img) | |||
| 8007 | { | |||
| 8008 | if ( img ) | |||
| 8009 | { | |||
| 8010 | img->path = ""; | |||
| 8011 | if ( entry.effect == kEffectBread || entry.effect == kEffectBloodHunger ) | |||
| 8012 | { | |||
| 8013 | if ( StatusEffectDefinitions_t::effectDefinitionExists(entry.effect) ) | |||
| 8014 | { | |||
| 8015 | int variation = -1; | |||
| 8016 | if ( entry.customVariable >= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_OVERSATIATED) ) | |||
| 8017 | { | |||
| 8018 | variation = 0; | |||
| 8019 | } | |||
| 8020 | else if ( entry.customVariable <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_STARVING) ) | |||
| 8021 | { | |||
| 8022 | variation = 3; | |||
| 8023 | } | |||
| 8024 | else if ( entry.customVariable <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_WEAK) ) | |||
| 8025 | { | |||
| 8026 | variation = 2; | |||
| 8027 | } | |||
| 8028 | else if ( entry.customVariable <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_HUNGRY) ) | |||
| 8029 | { | |||
| 8030 | variation = 1; | |||
| 8031 | } | |||
| 8032 | if ( variation >= 0 ) | |||
| 8033 | { | |||
| 8034 | img->path = StatusEffectDefinitions_t::getEffectImgPath(StatusEffectDefinitions_t::getEffect(entry.effect), variation); | |||
| 8035 | } | |||
| 8036 | else | |||
| 8037 | { | |||
| 8038 | img->path = ""; | |||
| 8039 | } | |||
| 8040 | } | |||
| 8041 | } | |||
| 8042 | else if ( entry.effect == kEffectAutomatonHunger ) | |||
| 8043 | { | |||
| 8044 | int variation = 1; | |||
| 8045 | if ( entry.customVariable >= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_AUTOMATON_SUPERHEATED) ) | |||
| 8046 | { | |||
| 8047 | variation = 0; | |||
| 8048 | } | |||
| 8049 | else if ( entry.customVariable <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_AUTOMATON_CRITICAL) ) | |||
| 8050 | { | |||
| 8051 | variation = 2; | |||
| 8052 | } | |||
| 8053 | img->path = StatusEffectDefinitions_t::getEffectImgPath(StatusEffectDefinitions_t::getEffect(entry.effect), variation); | |||
| 8054 | } | |||
| 8055 | else | |||
| 8056 | { | |||
| 8057 | if ( entry.effect >= kSpellEffectOffset ) | |||
| 8058 | { | |||
| 8059 | int effectID = entry.effect - kSpellEffectOffset; | |||
| 8060 | if ( StatusEffectDefinitions_t::sustainedSpellDefinitionExists(effectID) ) | |||
| 8061 | { | |||
| 8062 | img->path = StatusEffectDefinitions_t::getEffectImgPath(StatusEffectDefinitions_t::getSustainedSpell(effectID)); | |||
| 8063 | } | |||
| 8064 | } | |||
| 8065 | else | |||
| 8066 | { | |||
| 8067 | int effectID = entry.effect; | |||
| 8068 | if ( StatusEffectDefinitions_t::effectDefinitionExists(effectID) ) | |||
| 8069 | { | |||
| 8070 | int variation = -1; | |||
| 8071 | if ( effectID == EFF_SHAPESHIFT ) | |||
| 8072 | { | |||
| 8073 | if ( players[player] && players[player]->entity ) | |||
| 8074 | { | |||
| 8075 | switch ( players[player]->entity->effectShapeshift ) | |||
| 8076 | { | |||
| 8077 | case RAT: | |||
| 8078 | variation = 0; | |||
| 8079 | break; | |||
| 8080 | case SPIDER: | |||
| 8081 | variation = 1; | |||
| 8082 | break; | |||
| 8083 | case TROLL: | |||
| 8084 | variation = 2; | |||
| 8085 | break; | |||
| 8086 | case CREATURE_IMP: | |||
| 8087 | variation = 3; | |||
| 8088 | break; | |||
| 8089 | default: | |||
| 8090 | break; | |||
| 8091 | } | |||
| 8092 | } | |||
| 8093 | if ( variation == -1 ) | |||
| 8094 | { | |||
| 8095 | img->path = ""; | |||
| 8096 | } | |||
| 8097 | else | |||
| 8098 | { | |||
| 8099 | img->path = StatusEffectDefinitions_t::getEffectImgPath(StatusEffectDefinitions_t::getEffect(effectID), variation); | |||
| 8100 | } | |||
| 8101 | } | |||
| 8102 | else | |||
| 8103 | { | |||
| 8104 | img->path = StatusEffectDefinitions_t::getEffectImgPath(StatusEffectDefinitions_t::getEffect(effectID), variation); | |||
| 8105 | } | |||
| 8106 | } | |||
| 8107 | } | |||
| 8108 | } | |||
| 8109 | ||||
| 8110 | SDL_Rect dest{ 0, 0, entry.pos.w, entry.pos.h }; | |||
| 8111 | dest.x = entry.pos.x; | |||
| 8112 | dest.y = entry.pos.y; | |||
| 8113 | img->pos = dest; | |||
| 8114 | img->disabled = false; | |||
| 8115 | ||||
| 8116 | if ( img->path.size() > 1 && img->path[0] != '*' ) | |||
| 8117 | { | |||
| 8118 | img->path.insert(0, 1, '*'); | |||
| 8119 | } | |||
| 8120 | } | |||
| 8121 | } | |||
| 8122 | ||||
| 8123 | void updateStatusEffectQueue(const int player) | |||
| 8124 | { | |||
| 8125 | auto& statusEffectQueue = StatusEffectQueue[player]; | |||
| 8126 | Frame* statusEffectFrame = statusEffectQueue.getStatusEffectFrame(); | |||
| 8127 | if ( !statusEffectFrame ) | |||
| 8128 | { | |||
| 8129 | return; | |||
| 8130 | } | |||
| 8131 | if ( gamePaused && multiplayer == SINGLE0 ) | |||
| 8132 | { | |||
| 8133 | return; | |||
| 8134 | } | |||
| 8135 | auto& hud_t = players[player]->hud; | |||
| 8136 | SDL_Rect mainFramePos{ 0, 0, players[player]->camera_virtualWidth(), players[player]->camera_virtualHeight() / 2 }; | |||
| 8137 | mainFramePos.x = hud_t.hpFrame->getSize().x; | |||
| 8138 | mainFramePos.y = hud_t.hpFrame->getSize().y - mainFramePos.h; | |||
| 8139 | mainFramePos.w -= mainFramePos.x; | |||
| 8140 | if ( players[player]->hud.statusFxFocusedWindowActive ) | |||
| 8141 | { | |||
| 8142 | mainFramePos.x += 8 * statusEffectQueue.focusedWindowAnim; | |||
| 8143 | mainFramePos.y -= 8 * statusEffectQueue.focusedWindowAnim; | |||
| 8144 | } | |||
| 8145 | statusEffectFrame->setSize(mainFramePos); | |||
| 8146 | auto innerFrame = statusEffectFrame->findFrame("effects"); | |||
| 8147 | innerFrame->setSize(SDL_Rect{ 0, 0, statusEffectFrame->getSize().w, statusEffectFrame->getSize().h }); | |||
| 8148 | ||||
| 8149 | const int hungerEffectID = ((stats[player] && stats[player]->type == AUTOMATON) ? StatusEffectQueue_t::kEffectAutomatonHunger | |||
| 8150 | : (playerRequiresBloodToSustain(player) ? StatusEffectQueue_t::kEffectBloodHunger : StatusEffectQueue_t::kEffectBread)); | |||
| 8151 | ||||
| 8152 | // hunger icon | |||
| 8153 | if ( stats[player] && stats[player]->type != AUTOMATON ) | |||
| 8154 | { | |||
| 8155 | statusEffectQueue.deleteEffect(StatusEffectQueue_t::kEffectAutomatonHunger); | |||
| 8156 | } | |||
| 8157 | ||||
| 8158 | bool effectsEnabled = true; | |||
| 8159 | if ( !players[player]->entity && ((multiplayer == SINGLE0 && splitscreen) || multiplayer != SINGLE0) ) | |||
| 8160 | { | |||
| 8161 | effectsEnabled = false; | |||
| 8162 | } | |||
| 8163 | if ( players[player]->ghost.isActive() && !kAllowGhostStatusEffects ) | |||
| 8164 | { | |||
| 8165 | effectsEnabled = false; | |||
| 8166 | } | |||
| 8167 | ||||
| 8168 | if ( effectsEnabled && stats[player] && stats[player]->type != AUTOMATON | |||
| 8169 | && (svFlags & SV_FLAG_HUNGER) | |||
| 8170 | && (stats[player]->HUNGER <= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_HUNGRY) | |||
| 8171 | || stats[player]->HUNGER >= getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_OVERSATIATED)) ) | |||
| 8172 | { | |||
| 8173 | statusEffectQueue.deleteEffect(StatusEffectQueue_t::kEffectAutomatonHunger); | |||
| 8174 | if ( hungerEffectID == StatusEffectQueue_t::kEffectBloodHunger ) | |||
| 8175 | { | |||
| 8176 | statusEffectQueue.deleteEffect(StatusEffectQueue_t::kEffectBread); // delete opposite if present | |||
| 8177 | } | |||
| 8178 | if ( hungerEffectID == StatusEffectQueue_t::kEffectBread ) | |||
| 8179 | { | |||
| 8180 | statusEffectQueue.deleteEffect(StatusEffectQueue_t::kEffectBloodHunger); // delete opposite if present | |||
| 8181 | } | |||
| 8182 | ||||
| 8183 | const int HUNGER_NONE = 1000; | |||
| 8184 | const int HUNGER_OVERSATIATED = getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_OVERSATIATED); | |||
| 8185 | const int HUNGER_HUNGRY = getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_HUNGRY); | |||
| 8186 | const int HUNGER_WEAK = getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_WEAK); | |||
| 8187 | const int HUNGER_STARVING = getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_STARVING); | |||
| 8188 | int hungerStateToSet = HUNGER_NONE; | |||
| 8189 | if ( stats[player]->HUNGER >= HUNGER_OVERSATIATED ) | |||
| 8190 | { | |||
| 8191 | hungerStateToSet = HUNGER_OVERSATIATED; | |||
| 8192 | } | |||
| 8193 | else if ( stats[player]->HUNGER <= HUNGER_STARVING ) | |||
| 8194 | { | |||
| 8195 | hungerStateToSet = HUNGER_STARVING; | |||
| 8196 | } | |||
| 8197 | else if ( stats[player]->HUNGER <= HUNGER_WEAK ) | |||
| 8198 | { | |||
| 8199 | hungerStateToSet = HUNGER_WEAK; | |||
| 8200 | } | |||
| 8201 | else if ( stats[player]->HUNGER <= HUNGER_HUNGRY ) | |||
| 8202 | { | |||
| 8203 | hungerStateToSet = HUNGER_HUNGRY; | |||
| 8204 | } | |||
| 8205 | StatusEffectQueueEntry_t* entry = nullptr; | |||
| 8206 | StatusEffectQueueEntry_t* notif = nullptr; | |||
| 8207 | ||||
| 8208 | ||||
| 8209 | for ( auto& q : statusEffectQueue.effectQueue ) | |||
| 8210 | { | |||
| 8211 | if ( q.effect == hungerEffectID ) | |||
| 8212 | { | |||
| 8213 | entry = &(q); | |||
| 8214 | for ( auto& n : statusEffectQueue.notificationQueue ) | |||
| 8215 | { | |||
| 8216 | if ( n.effect == hungerEffectID ) | |||
| 8217 | { | |||
| 8218 | notif = &(n); | |||
| 8219 | } | |||
| 8220 | break; | |||
| 8221 | } | |||
| 8222 | break; | |||
| 8223 | } | |||
| 8224 | } | |||
| 8225 | if ( entry && entry->customVariable != hungerStateToSet ) | |||
| 8226 | { | |||
| 8227 | if ( notif && notif->customVariable != hungerStateToSet ) | |||
| 8228 | { | |||
| 8229 | // reset the notification | |||
| 8230 | bool erased = false; | |||
| 8231 | for ( auto it = statusEffectQueue.notificationQueue.begin(); it != statusEffectQueue.notificationQueue.end(); ++it ) | |||
| 8232 | { | |||
| 8233 | if ( (*it).effect == hungerEffectID ) | |||
| 8234 | { | |||
| 8235 | statusEffectQueue.notificationQueue.erase(it); | |||
| 8236 | erased = true; | |||
| 8237 | break; | |||
| 8238 | } | |||
| 8239 | } | |||
| 8240 | statusEffectQueue.notificationQueue.push_back(StatusEffectQueueEntry_t(hungerEffectID)); | |||
| 8241 | statusEffectQueue.notificationQueue.back().pos.x = statusEffectQueue.getBaseEffectPosX(); | |||
| 8242 | statusEffectQueue.notificationQueue.back().pos.y = statusEffectQueue.getBaseEffectPosY(); | |||
| 8243 | ||||
| 8244 | // fall back if notificationTargetPosition doesn't have an effect to go to. | |||
| 8245 | statusEffectQueue.notificationQueue.back().notificationTargetPosition.x = 0; | |||
| 8246 | statusEffectQueue.notificationQueue.back().notificationTargetPosition.y = statusEffectQueue.statusEffectFrame->getSize().h | |||
| 8247 | - statusEffectQueue.notificationQueue.back().notificationTargetPosition.h; | |||
| 8248 | statusEffectQueue.requiresAnimUpdate = true; | |||
| 8249 | entry->customVariable = hungerStateToSet; | |||
| 8250 | statusEffectQueue.notificationQueue.back().customVariable = hungerStateToSet; | |||
| 8251 | } | |||
| 8252 | else | |||
| 8253 | { | |||
| 8254 | // else, delete and reapply | |||
| 8255 | statusEffectQueue.deleteEffect(hungerEffectID); | |||
| 8256 | if ( statusEffectQueue.insertEffect(hungerEffectID, -1) ) | |||
| 8257 | { | |||
| 8258 | if ( statusEffectQueue.effectQueue.back().effect == hungerEffectID ) | |||
| 8259 | { | |||
| 8260 | statusEffectQueue.effectQueue.back().customVariable = hungerStateToSet; | |||
| 8261 | statusEffectQueue.notificationQueue.back().customVariable = hungerStateToSet; | |||
| 8262 | } | |||
| 8263 | } | |||
| 8264 | } | |||
| 8265 | } | |||
| 8266 | else | |||
| 8267 | { | |||
| 8268 | // new effect, does not exist | |||
| 8269 | if ( statusEffectQueue.insertEffect(hungerEffectID, -1) ) | |||
| 8270 | { | |||
| 8271 | if ( statusEffectQueue.effectQueue.back().effect == hungerEffectID ) | |||
| 8272 | { | |||
| 8273 | statusEffectQueue.effectQueue.back().customVariable = hungerStateToSet; | |||
| 8274 | statusEffectQueue.notificationQueue.back().customVariable = hungerStateToSet; | |||
| 8275 | } | |||
| 8276 | } | |||
| 8277 | } | |||
| 8278 | } | |||
| 8279 | else if ( effectsEnabled ) | |||
| 8280 | { | |||
| 8281 | statusEffectQueue.deleteEffect(StatusEffectQueue_t::kEffectBloodHunger); | |||
| 8282 | statusEffectQueue.deleteEffect(StatusEffectQueue_t::kEffectBread); | |||
| 8283 | ||||
| 8284 | if ( hungerEffectID == StatusEffectQueue_t::kEffectAutomatonHunger ) | |||
| 8285 | { | |||
| 8286 | const int HUNGER_NONE = 1000; | |||
| 8287 | const int HUNGER_SUPERHEATED = getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_AUTOMATON_SUPERHEATED); | |||
| 8288 | const int HUNGER_CRITICAL = getEntityHungerInterval(player, nullptr, stats[player], HUNGER_INTERVAL_AUTOMATON_CRITICAL); | |||
| 8289 | int hungerStateToSet = HUNGER_NONE; | |||
| 8290 | if ( stats[player]->HUNGER >= HUNGER_SUPERHEATED ) | |||
| 8291 | { | |||
| 8292 | hungerStateToSet = HUNGER_SUPERHEATED; | |||
| 8293 | } | |||
| 8294 | else if ( stats[player]->HUNGER <= HUNGER_CRITICAL ) | |||
| 8295 | { | |||
| 8296 | hungerStateToSet = HUNGER_CRITICAL; | |||
| 8297 | } | |||
| 8298 | StatusEffectQueueEntry_t* entry = nullptr; | |||
| 8299 | StatusEffectQueueEntry_t* notif = nullptr; | |||
| 8300 | ||||
| 8301 | for ( auto& q : statusEffectQueue.effectQueue ) | |||
| 8302 | { | |||
| 8303 | if ( q.effect == hungerEffectID ) | |||
| 8304 | { | |||
| 8305 | entry = &(q); | |||
| 8306 | for ( auto& n : statusEffectQueue.notificationQueue ) | |||
| 8307 | { | |||
| 8308 | if ( n.effect == hungerEffectID ) | |||
| 8309 | { | |||
| 8310 | notif = &(n); | |||
| 8311 | } | |||
| 8312 | break; | |||
| 8313 | } | |||
| 8314 | break; | |||
| 8315 | } | |||
| 8316 | } | |||
| 8317 | if ( entry && entry->customVariable != hungerStateToSet ) | |||
| 8318 | { | |||
| 8319 | if ( notif && notif->customVariable != hungerStateToSet ) | |||
| 8320 | { | |||
| 8321 | // reset the notification | |||
| 8322 | bool erased = false; | |||
| 8323 | for ( auto it = statusEffectQueue.notificationQueue.begin(); it != statusEffectQueue.notificationQueue.end(); ++it ) | |||
| 8324 | { | |||
| 8325 | if ( (*it).effect == hungerEffectID ) | |||
| 8326 | { | |||
| 8327 | statusEffectQueue.notificationQueue.erase(it); | |||
| 8328 | erased = true; | |||
| 8329 | break; | |||
| 8330 | } | |||
| 8331 | } | |||
| 8332 | statusEffectQueue.notificationQueue.push_back(StatusEffectQueueEntry_t(hungerEffectID)); | |||
| 8333 | statusEffectQueue.notificationQueue.back().pos.x = statusEffectQueue.getBaseEffectPosX(); | |||
| 8334 | statusEffectQueue.notificationQueue.back().pos.y = statusEffectQueue.getBaseEffectPosY(); | |||
| 8335 | ||||
| 8336 | // fall back if notificationTargetPosition doesn't have an effect to go to. | |||
| 8337 | statusEffectQueue.notificationQueue.back().notificationTargetPosition.x = 0; | |||
| 8338 | statusEffectQueue.notificationQueue.back().notificationTargetPosition.y = statusEffectFrame->getSize().h | |||
| 8339 | - statusEffectQueue.notificationQueue.back().notificationTargetPosition.h; | |||
| 8340 | statusEffectQueue.requiresAnimUpdate = true; | |||
| 8341 | entry->customVariable = hungerStateToSet; | |||
| 8342 | statusEffectQueue.notificationQueue.back().customVariable = hungerStateToSet; | |||
| 8343 | } | |||
| 8344 | else | |||
| 8345 | { | |||
| 8346 | // else, delete and reapply | |||
| 8347 | statusEffectQueue.deleteEffect(hungerEffectID); | |||
| 8348 | if ( statusEffectQueue.insertEffect(hungerEffectID, -1) ) | |||
| 8349 | { | |||
| 8350 | if ( statusEffectQueue.effectQueue.back().effect == hungerEffectID ) | |||
| 8351 | { | |||
| 8352 | statusEffectQueue.effectQueue.back().customVariable = hungerStateToSet; | |||
| 8353 | statusEffectQueue.notificationQueue.back().customVariable = hungerStateToSet; | |||
| 8354 | } | |||
| 8355 | } | |||
| 8356 | } | |||
| 8357 | } | |||
| 8358 | else | |||
| 8359 | { | |||
| 8360 | // new effect, does not exist | |||
| 8361 | if ( statusEffectQueue.insertEffect(hungerEffectID, -1) ) | |||
| 8362 | { | |||
| 8363 | if ( statusEffectQueue.effectQueue.back().effect == hungerEffectID ) | |||
| 8364 | { | |||
| 8365 | statusEffectQueue.effectQueue.back().customVariable = hungerStateToSet; | |||
| 8366 | statusEffectQueue.notificationQueue.back().customVariable = hungerStateToSet; | |||
| 8367 | } | |||
| 8368 | } | |||
| 8369 | } | |||
| 8370 | } | |||
| 8371 | } | |||
| 8372 | ||||
| 8373 | statusEffectQueue.updateAllQueuedEffects(); | |||
| 8374 | } | |||
| 8375 | ||||
| 8376 | void Player::Inventory_t::updateInventoryMiscTooltip() | |||
| 8377 | { | |||
| 8378 | if ( !frame ) | |||
| 8379 | { | |||
| 8380 | return; | |||
| 8381 | } | |||
| 8382 | if ( !miscTooltipFrame ) | |||
| 8383 | { | |||
| 8384 | auto tooltipFrame = frame->addFrame("misc tooltip"); | |||
| 8385 | miscTooltipFrame = tooltipFrame; | |||
| 8386 | tooltipFrame->setSize(SDL_Rect{ 212, 0, 200, 200 }); | |||
| 8387 | tooltipFrame->setHollow(true); | |||
| 8388 | tooltipFrame->setInheritParentFrameOpacity(false); | |||
| 8389 | tooltipFrame->setDisabled(true); | |||
| 8390 | Uint32 color = makeColor(255, 255, 255, 255); | |||
| 8391 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 8392 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TL_00.png", skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 8393 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 8394 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TR_00.png", skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 8395 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 8396 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_T_00.png", skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 8397 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 8398 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_L_00.png", skillsheetEffectBackgroundImages[MIDDLE_LEFT].c_str()); | |||
| 8399 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 8400 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_R_00.png", skillsheetEffectBackgroundImages[MIDDLE_RIGHT].c_str()); | |||
| 8401 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 8402 | makeColor(22, 24, 29, 255), "images/system/white.png", skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 8403 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 8404 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_BL_00.png", skillsheetEffectBackgroundImages[BOTTOM_LEFT].c_str()); | |||
| 8405 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 8406 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_BR_00.png", skillsheetEffectBackgroundImages[BOTTOM_RIGHT].c_str()); | |||
| 8407 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 8408 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_B_00.png", skillsheetEffectBackgroundImages[BOTTOM].c_str()); | |||
| 8409 | imageSetWidthHeight9x9(tooltipFrame, skillsheetEffectBackgroundImages); | |||
| 8410 | imageResizeToContainer9x9(tooltipFrame, SDL_Rect{ 0, 0, 200, 200 }, skillsheetEffectBackgroundImages); | |||
| 8411 | auto txt = tooltipFrame->addField("tooltip text", 1024); | |||
| 8412 | const char* tooltipFont = "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 8413 | txt->setFont(tooltipFont); | |||
| 8414 | txt->setColor(makeColor(188, 154, 114, 255)); | |||
| 8415 | } | |||
| 8416 | ||||
| 8417 | auto tooltipFrame = miscTooltipFrame; | |||
| 8418 | if ( tooltipFrame->isDisabled() ) | |||
| 8419 | { | |||
| 8420 | miscTooltipOpacitySetpoint = 0; | |||
| 8421 | miscTooltipOpacityAnimate = 1.0; | |||
| 8422 | } | |||
| 8423 | ||||
| 8424 | if ( static_cast<int>(tooltipFrame->getOpacity()) != miscTooltipOpacitySetpoint ) | |||
| 8425 | { | |||
| 8426 | const real_t fpsScale = getFPSScale(144.0); | |||
| 8427 | if ( miscTooltipOpacitySetpoint == 0 ) | |||
| 8428 | { | |||
| 8429 | if ( ticks - miscTooltipDeselectedTick > 5 ) | |||
| 8430 | { | |||
| 8431 | real_t factor = 10.0; | |||
| 8432 | real_t setpointDiff = fpsScale * std::max(.05, (miscTooltipOpacityAnimate)) / (factor); | |||
| 8433 | miscTooltipOpacityAnimate -= setpointDiff; | |||
| 8434 | miscTooltipOpacityAnimate = std::max(0.0, miscTooltipOpacityAnimate); | |||
| 8435 | } | |||
| 8436 | } | |||
| 8437 | else | |||
| 8438 | { | |||
| 8439 | real_t setpointDiff = fpsScale * std::max(.05, (1.0 - miscTooltipOpacityAnimate)) / (1); | |||
| 8440 | miscTooltipOpacityAnimate += setpointDiff; | |||
| 8441 | miscTooltipOpacityAnimate = std::min(1.0, miscTooltipOpacityAnimate); | |||
| 8442 | } | |||
| 8443 | tooltipFrame->setOpacity(miscTooltipOpacityAnimate * 100); | |||
| 8444 | } | |||
| 8445 | else | |||
| 8446 | { | |||
| 8447 | tooltipFrame->setOpacity(miscTooltipOpacitySetpoint); | |||
| 8448 | } | |||
| 8449 | ||||
| 8450 | Button* autosortBtn = nullptr; | |||
| 8451 | if ( player.shootmode ) | |||
| 8452 | { | |||
| 8453 | miscTooltipOpacitySetpoint = 0; | |||
| 8454 | miscTooltipOpacityAnimate = 0.0; | |||
| 8455 | return; | |||
| 8456 | } | |||
| 8457 | if ( !playerInventoryFrames[player.playernum].autosortFrame ) | |||
| 8458 | { | |||
| 8459 | return; | |||
| 8460 | } | |||
| 8461 | else | |||
| 8462 | { | |||
| 8463 | autosortBtn = playerInventoryFrames[player.playernum].autosortFrame->findButton("autosort button"); | |||
| 8464 | if ( !autosortBtn || !autosortBtn->isHighlighted() || !autosortBtn->isSelected() || autosortBtn->isDisabled() ) | |||
| 8465 | { | |||
| 8466 | return; | |||
| 8467 | } | |||
| 8468 | } | |||
| 8469 | ||||
| 8470 | miscTooltipOpacitySetpoint = 0; | |||
| 8471 | miscTooltipOpacityAnimate = 1.0; | |||
| 8472 | tooltipFrame->setDisabled(false); | |||
| 8473 | tooltipFrame->setOpacity(100.0); | |||
| 8474 | miscTooltipDeselectedTick = ticks; | |||
| 8475 | ||||
| 8476 | Uint32 defaultColor = hudColors.characterSheetNeutral; | |||
| 8477 | auto txt = tooltipFrame->findField("tooltip text"); | |||
| 8478 | txt->setColor(defaultColor); | |||
| 8479 | ||||
| 8480 | if ( true ) | |||
| 8481 | { | |||
| 8482 | const int maxWidth = 200; | |||
| 8483 | const int padx = 16; | |||
| 8484 | const int pady1 = 8; | |||
| 8485 | const int pady2 = 8; | |||
| 8486 | const int padyMid = 4; | |||
| 8487 | const int padxMid = 4; | |||
| 8488 | SDL_Rect tooltipPos = SDL_Rect{ 400, 0, maxWidth, 100 }; | |||
| 8489 | bool usingMouse = !inputs.getVirtualMouse(player.playernum)->lastMovementFromController; | |||
| 8490 | bool updateTxt = false; | |||
| 8491 | if ( player.bUseCompactGUIHeight() ) | |||
| 8492 | { | |||
| 8493 | if ( strcmp(player.characterSheet.getHoverTextString("autosort_button_mouse_compact").c_str(), txt->getText()) ) | |||
| 8494 | { | |||
| 8495 | txt->setText(player.characterSheet.getHoverTextString("autosort_button_mouse_compact").c_str()); | |||
| 8496 | updateTxt = true; | |||
| 8497 | } | |||
| 8498 | } | |||
| 8499 | else | |||
| 8500 | { | |||
| 8501 | if ( strcmp(player.characterSheet.getHoverTextString("autosort_button_mouse").c_str(), txt->getText()) ) | |||
| 8502 | { | |||
| 8503 | txt->setText(player.characterSheet.getHoverTextString("autosort_button_mouse").c_str()); | |||
| 8504 | updateTxt = true; | |||
| 8505 | } | |||
| 8506 | } | |||
| 8507 | ||||
| 8508 | SDL_Rect txtPos = SDL_Rect{ padx, pady1, maxWidth - padx * 2, 80 }; | |||
| 8509 | txt->setSize(txtPos); | |||
| 8510 | Font* actualFont = Font::get(txt->getFont()); | |||
| 8511 | int txtHeight = txt->getNumTextLines() * actualFont->height(true); | |||
| 8512 | txtPos.h = txtHeight + padyMid; | |||
| 8513 | auto txtGet = Text::get(txt->getLongestLine().c_str(), txt->getFont(), | |||
| 8514 | txt->getTextColor(), txt->getOutlineColor()); | |||
| 8515 | txtPos.w = txtGet->getWidth(); | |||
| 8516 | txt->setSize(txtPos); | |||
| 8517 | ||||
| 8518 | tooltipPos.w = txtPos.w + padx * 2; | |||
| 8519 | tooltipPos.h = pady1 + txtPos.h + pady2; | |||
| 8520 | ||||
| 8521 | if ( updateTxt ) | |||
| 8522 | { | |||
| 8523 | txt->reflowTextToFit(0); | |||
| 8524 | } | |||
| 8525 | ||||
| 8526 | int tooltipCoordX = 0; | |||
| 8527 | PanelJustify_t justify = paperDollPanelJustify; | |||
| 8528 | auto inventoryBgFrame = playerInventoryFrames[player.playernum].inventoryBgFrame; | |||
| 8529 | if ( !bCompactView ) | |||
| 8530 | { | |||
| 8531 | Frame::image_t* invBaseImg = invBaseImg = playerInventoryFrames[player.playernum].defaultInvImg; | |||
| 8532 | ||||
| 8533 | if ( justify == PANEL_JUSTIFY_LEFT ) | |||
| 8534 | { | |||
| 8535 | tooltipCoordX = inventoryBgFrame->getSize().x + 8; | |||
| 8536 | tooltipCoordX += invBaseImg->pos.w; | |||
| 8537 | } | |||
| 8538 | else | |||
| 8539 | { | |||
| 8540 | tooltipCoordX = inventoryBgFrame->getSize().x - 8; | |||
| 8541 | tooltipCoordX += invBaseImg->pos.x; | |||
| 8542 | tooltipCoordX -= tooltipPos.w; | |||
| 8543 | } | |||
| 8544 | } | |||
| 8545 | else | |||
| 8546 | { | |||
| 8547 | Frame::image_t* compactImg = compactImg = playerInventoryFrames[player.playernum].compactCharImg; | |||
| 8548 | if ( justify == PANEL_JUSTIFY_LEFT ) | |||
| 8549 | { | |||
| 8550 | tooltipCoordX = inventoryBgFrame->getSize().x + 8; | |||
| 8551 | tooltipCoordX += compactImg->pos.w; | |||
| 8552 | } | |||
| 8553 | else | |||
| 8554 | { | |||
| 8555 | tooltipCoordX = inventoryBgFrame->getSize().x - 8; | |||
| 8556 | tooltipCoordX += compactImg->pos.x; | |||
| 8557 | tooltipCoordX -= tooltipPos.w; | |||
| 8558 | } | |||
| 8559 | } | |||
| 8560 | tooltipPos.x = tooltipCoordX; | |||
| 8561 | tooltipPos.y = autosortBtn->getSize().y; | |||
| 8562 | tooltipFrame->setSize(tooltipPos); | |||
| 8563 | imageResizeToContainer9x9(tooltipFrame, SDL_Rect{ 0, 0, tooltipPos.w, tooltipPos.h }, | |||
| 8564 | skillsheetEffectBackgroundImages); | |||
| 8565 | } | |||
| 8566 | } | |||
| 8567 | ||||
| 8568 | void createWorldTooltipPrompts(const int player) | |||
| 8569 | { | |||
| 8570 | auto& hud_t = players[player]->hud; | |||
| 8571 | auto& worldTooltipFrame = hud_t.worldTooltipFrame; | |||
| 8572 | worldTooltipFrame = hud_t.hudFrame->addFrame("world tooltip"); | |||
| 8573 | worldTooltipFrame->setHollow(true); | |||
| 8574 | worldTooltipFrame->setBorder(0); | |||
| 8575 | worldTooltipFrame->setOwner(player); | |||
| 8576 | worldTooltipFrame->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 8577 | worldTooltipFrame->setDisabled(true); | |||
| 8578 | ||||
| 8579 | const char* promptFont = "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 8580 | ||||
| 8581 | Uint32 iconColor = makeColor(255, 255, 255, Player::HUD_t::actionPromptIconOpacity); | |||
| 8582 | Uint32 iconBackingColor = makeColor(255, 255, 255, Player::HUD_t::actionPromptIconBackingOpacity); | |||
| 8583 | ||||
| 8584 | auto text = worldTooltipFrame->addField("prompt text", 256); | |||
| 8585 | text->setFont(promptFont); | |||
| 8586 | text->setText(""); | |||
| 8587 | text->setDisabled(true); | |||
| 8588 | text->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 8589 | ||||
| 8590 | auto text2 = worldTooltipFrame->addField("prompt cycle text", 256); | |||
| 8591 | text2->setFont(promptFont); | |||
| 8592 | text2->setText(""); | |||
| 8593 | text2->setDisabled(true); | |||
| 8594 | text2->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 8595 | ||||
| 8596 | auto text3 = worldTooltipFrame->addField("prompt callout text", 256); | |||
| 8597 | text3->setFont(promptFont); | |||
| 8598 | text3->setText(""); | |||
| 8599 | text3->setDisabled(true); | |||
| 8600 | text3->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 8601 | ||||
| 8602 | const int iconSize = 24; | |||
| 8603 | SDL_Rect iconPos{ 0, 0, iconSize, iconSize }; | |||
| 8604 | ||||
| 8605 | auto icon = worldTooltipFrame->addImage(iconPos, | |||
| 8606 | iconColor, "images/system/white.png", "icon img"); | |||
| 8607 | icon->disabled = true; | |||
| 8608 | ||||
| 8609 | auto glyph = worldTooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 8610 | 0xFFFFFFFF, "images/system/white.png", "glyph img"); | |||
| 8611 | glyph->disabled = true; | |||
| 8612 | ||||
| 8613 | auto glyphAdditional = worldTooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 8614 | 0xFFFFFFFF, "images/system/white.png", "glyph img 2"); | |||
| 8615 | glyphAdditional->disabled = true; | |||
| 8616 | ||||
| 8617 | auto glyphAdditional2 = worldTooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 8618 | 0xFFFFFFFF, "images/system/white.png", "glyph img 3"); | |||
| 8619 | glyphAdditional2->disabled = true; | |||
| 8620 | ||||
| 8621 | auto glyphAdditional3 = worldTooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 8622 | 0xFFFFFFFF, "images/system/white.png", "glyph img 4"); | |||
| 8623 | glyphAdditional3->disabled = true; | |||
| 8624 | ||||
| 8625 | auto cursor = worldTooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 8626 | 0xFFFFFFFF, "images/system/white.png", "cursor img"); | |||
| 8627 | cursor->disabled = true; | |||
| 8628 | } | |||
| 8629 | ||||
| 8630 | const char* Player::HUD_t::getCrosshairPath() | |||
| 8631 | { | |||
| 8632 | switch ( playerSettings[multiplayer ? 0 : player.playernum].shootmodeCrosshair ) | |||
| 8633 | { | |||
| 8634 | case 0: | |||
| 8635 | default: | |||
| 8636 | return "*#images/ui/Crosshairs/cross.png"; | |||
| 8637 | break; | |||
| 8638 | case 1: | |||
| 8639 | return "*#images/ui/Crosshairs/cursor_thicc.png"; | |||
| 8640 | break; | |||
| 8641 | case 2: | |||
| 8642 | return "*#images/ui/Crosshairs/cursor_plusA.png"; | |||
| 8643 | break; | |||
| 8644 | case 3: | |||
| 8645 | return "*#images/ui/Crosshairs/cursor_plusB.png"; | |||
| 8646 | break; | |||
| 8647 | case 4: | |||
| 8648 | return "*#images/ui/Crosshairs/cursor_crosshair.png"; | |||
| 8649 | break; | |||
| 8650 | case 5: | |||
| 8651 | return "*#images/ui/Crosshairs/cursor_xB.png"; | |||
| 8652 | break; | |||
| 8653 | case 6: | |||
| 8654 | return "*#images/ui/Crosshairs/cursor_carrot.png"; | |||
| 8655 | break; | |||
| 8656 | case 7: | |||
| 8657 | return "*#images/ui/Crosshairs/cursor_circleB.png"; | |||
| 8658 | break; | |||
| 8659 | case 8: | |||
| 8660 | return "*#images/ui/Crosshairs/cursor_dotsB.png"; | |||
| 8661 | break; | |||
| 8662 | case 9: | |||
| 8663 | return "*#images/ui/Crosshairs/cursor_dotsC.png"; | |||
| 8664 | break; | |||
| 8665 | case 10: | |||
| 8666 | return "*#images/ui/Crosshairs/cursor_smiley.png"; | |||
| 8667 | break; | |||
| 8668 | case 11: | |||
| 8669 | return "*#images/ui/Crosshairs/cursor_nethack.png"; | |||
| 8670 | break; | |||
| 8671 | } | |||
| 8672 | } | |||
| 8673 | ||||
| 8674 | void Player::HUD_t::updateWorldTooltipPrompts() | |||
| 8675 | { | |||
| 8676 | if ( !hudFrame ) | |||
| 8677 | { | |||
| 8678 | return; | |||
| 8679 | } | |||
| 8680 | ||||
| 8681 | if ( !worldTooltipFrame ) | |||
| 8682 | { | |||
| 8683 | createWorldTooltipPrompts(player.playernum); | |||
| 8684 | if ( !worldTooltipFrame ) | |||
| 8685 | { | |||
| 8686 | return; | |||
| 8687 | } | |||
| 8688 | } | |||
| 8689 | ||||
| 8690 | worldTooltipFrame->setDisabled(true); | |||
| 8691 | ||||
| 8692 | if ( !player.shootmode || nohud || gamePaused ) | |||
| 8693 | { | |||
| 8694 | return; | |||
| 8695 | } | |||
| 8696 | ||||
| 8697 | SDL_Rect promptPos{ player.camera_virtualWidth() / 2, player.camera_virtualHeight() / 2, 0, 0 }; | |||
| 8698 | ||||
| 8699 | FollowerRadialMenu& followerMenu = FollowerMenu[player.playernum]; | |||
| 8700 | CalloutRadialMenu& calloutMenu = CalloutMenu[player.playernum]; | |||
| 8701 | ||||
| 8702 | auto icon = worldTooltipFrame->findImage("icon img"); | |||
| 8703 | icon->disabled = true; | |||
| 8704 | auto glyph = worldTooltipFrame->findImage("glyph img"); | |||
| 8705 | glyph->disabled = true; | |||
| 8706 | auto glyphAdditional = worldTooltipFrame->findImage("glyph img 2"); | |||
| 8707 | glyphAdditional->disabled = true; | |||
| 8708 | auto cursor = worldTooltipFrame->findImage("cursor img"); | |||
| 8709 | cursor->disabled = true; | |||
| 8710 | auto text = worldTooltipFrame->findField("prompt text"); | |||
| 8711 | text->setDisabled(true); | |||
| 8712 | auto textCycle = worldTooltipFrame->findField("prompt cycle text"); | |||
| 8713 | textCycle->setDisabled(true); | |||
| 8714 | auto textCallout = worldTooltipFrame->findField("prompt callout text"); | |||
| 8715 | textCallout->setDisabled(true); | |||
| 8716 | auto glyphCycle = worldTooltipFrame->findImage("glyph img 3"); | |||
| 8717 | glyphCycle->disabled = true; | |||
| 8718 | auto glyphCallout = worldTooltipFrame->findImage("glyph img 4"); | |||
| 8719 | glyphCallout->disabled = true; | |||
| 8720 | ||||
| 8721 | SDL_Rect textPos{ 0, 0, 0, 0 }; | |||
| 8722 | const int skillIconToGlyphPadding = 4; | |||
| 8723 | const int nominalGlyphHeight = 26; | |||
| 8724 | ||||
| 8725 | bool usingTinkeringKit = false; | |||
| 8726 | bool useBracketsReticle = false; | |||
| 8727 | bool useSneakingReticle = false; | |||
| 8728 | if ( player.entity && stats[player.playernum] ) { | |||
| 8729 | if ( stats[player.playernum]->defending ) { | |||
| 8730 | auto shield = stats[player.playernum]->shield; | |||
| 8731 | if ( shield && shield->type == TOOL_TINKERING_KIT ) { | |||
| 8732 | useBracketsReticle = true; | |||
| 8733 | usingTinkeringKit = true; | |||
| 8734 | } | |||
| 8735 | } | |||
| 8736 | if ( stats[player.playernum]->sneaking ) { | |||
| 8737 | useBracketsReticle = true; | |||
| 8738 | useSneakingReticle = true; | |||
| 8739 | } | |||
| 8740 | } | |||
| 8741 | else if ( player.ghost.isActive() ) | |||
| 8742 | { | |||
| 8743 | if ( player.ghost.my->skill[3] == 1 ) | |||
| 8744 | { | |||
| 8745 | useSneakingReticle = true; | |||
| 8746 | } | |||
| 8747 | } | |||
| 8748 | ||||
| 8749 | bool followerInteract = followerMenu.selectMoveTo && (followerMenu.optionSelected == ALLY_CMD_MOVETO_SELECT | |||
| 8750 | || followerMenu.optionSelected == ALLY_CMD_ATTACK_SELECT); | |||
| 8751 | bool calloutInteract = calloutMenu.selectMoveTo && (calloutMenu.optionSelected == CalloutRadialMenu::CALLOUT_CMD_SELECT); | |||
| 8752 | ||||
| 8753 | if ( followerInteract || calloutInteract ) | |||
| 8754 | { | |||
| 8755 | bool forceBlankInteractText = false; | |||
| 8756 | auto optionSelected = followerInteract ? followerMenu.optionSelected : calloutMenu.optionSelected; | |||
| 8757 | if ( !player.worldUI.isEnabled() ) | |||
| 8758 | { | |||
| 8759 | cursor->path = "#*images/ui/Crosshairs/cursor_xB.png"; | |||
| 8760 | if ( auto imgGet = Image::get(cursor->path.c_str()) ) | |||
| 8761 | { | |||
| 8762 | cursor->disabled = false; | |||
| 8763 | promptPos.x -= (int)imgGet->getWidth() / 2; | |||
| 8764 | promptPos.y -= (int)imgGet->getHeight() / 2; | |||
| 8765 | SDL_Rect cursorPos{ 0, 0, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 8766 | cursor->pos = cursorPos; | |||
| 8767 | cursor->color = makeColor(255, 255, 255, 191); | |||
| 8768 | } | |||
| 8769 | textPos.x = cursor->pos.x + 24; | |||
| 8770 | textPos.y = cursor->pos.y + 20; | |||
| 8771 | } | |||
| 8772 | else | |||
| 8773 | { | |||
| 8774 | if ( optionSelected == ALLY_CMD_MOVETO_SELECT ) | |||
| 8775 | { | |||
| 8776 | cursor->path = "#*images/ui/Crosshairs/cursor_xB.png"; | |||
| 8777 | if ( auto imgGet = Image::get(cursor->path.c_str()) ) | |||
| 8778 | { | |||
| 8779 | cursor->disabled = false; | |||
| 8780 | promptPos.x -= (int)imgGet->getWidth() / 2; | |||
| 8781 | promptPos.y -= (int)imgGet->getHeight() / 2; | |||
| 8782 | SDL_Rect cursorPos{ 0, 0, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 8783 | cursor->pos = cursorPos; | |||
| 8784 | cursor->color = makeColor(255, 255, 255, 191); | |||
| 8785 | } | |||
| 8786 | ||||
| 8787 | textPos.x = cursor->pos.x + cursor->pos.w / 2; | |||
| 8788 | textPos.y = cursor->pos.y + cursor->pos.h / 2; | |||
| 8789 | if ( auto imgGet = Image::get("images/system/selectedcursor.png") ) | |||
| 8790 | { | |||
| 8791 | textPos.x -= (int)imgGet->getWidth() / 2; | |||
| 8792 | textPos.y -= (int)imgGet->getHeight() / 2; | |||
| 8793 | } | |||
| 8794 | ||||
| 8795 | if ( textPos.x < 0 ) | |||
| 8796 | { | |||
| 8797 | promptPos.x += textPos.x; | |||
| 8798 | cursor->pos.x -= textPos.x; | |||
| 8799 | textPos.x = 0; | |||
| 8800 | } | |||
| 8801 | if ( textPos.y < 0 ) | |||
| 8802 | { | |||
| 8803 | promptPos.y += textPos.y; | |||
| 8804 | cursor->pos.y -= textPos.y; | |||
| 8805 | textPos.y = 0; | |||
| 8806 | } | |||
| 8807 | } | |||
| 8808 | else | |||
| 8809 | { | |||
| 8810 | if ( player.worldUI.isEnabled() && !player.worldUI.bTooltipInView ) | |||
| 8811 | { | |||
| 8812 | forceBlankInteractText = true; | |||
| 8813 | ||||
| 8814 | cursor->path = getCrosshairPath(); | |||
| 8815 | if ( auto imgGet = Image::get(cursor->path.c_str()) ) | |||
| 8816 | { | |||
| 8817 | cursor->disabled = false; | |||
| 8818 | promptPos.x -= (int)imgGet->getWidth() / 2; | |||
| 8819 | promptPos.y -= (int)imgGet->getHeight() / 2; | |||
| 8820 | SDL_Rect cursorPos{ 0, 0, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 8821 | cursor->pos = cursorPos; | |||
| 8822 | cursor->color = makeColor(255, 255, 255, 255 * playerSettings[multiplayer ? 0 : player.playernum].shootmodeCrosshairOpacity / 100.f); | |||
| 8823 | } | |||
| 8824 | ||||
| 8825 | textPos.x = cursor->pos.x + cursor->pos.w / 2; | |||
| 8826 | textPos.y = cursor->pos.y + cursor->pos.h / 2; | |||
| 8827 | if ( auto imgGet = Image::get("images/system/selectedcursor.png") ) | |||
| 8828 | { | |||
| 8829 | textPos.x -= (int)imgGet->getWidth() / 2; | |||
| 8830 | textPos.y -= (int)imgGet->getHeight() / 2; | |||
| 8831 | } | |||
| 8832 | ||||
| 8833 | if ( textPos.x < 0 ) | |||
| 8834 | { | |||
| 8835 | promptPos.x += textPos.x; | |||
| 8836 | cursor->pos.x -= textPos.x; | |||
| 8837 | textPos.x = 0; | |||
| 8838 | } | |||
| 8839 | if ( textPos.y < 0 ) | |||
| 8840 | { | |||
| 8841 | promptPos.y += textPos.y; | |||
| 8842 | cursor->pos.y -= textPos.y; | |||
| 8843 | textPos.y = 0; | |||
| 8844 | } | |||
| 8845 | } | |||
| 8846 | else | |||
| 8847 | { | |||
| 8848 | cursor->path = "images/system/selectedcursor.png"; | |||
| 8849 | if ( auto imgGet = Image::get(cursor->path.c_str()) ) | |||
| 8850 | { | |||
| 8851 | cursor->disabled = false; | |||
| 8852 | promptPos.x -= (int)imgGet->getWidth() / 2; | |||
| 8853 | promptPos.y -= (int)imgGet->getHeight() / 2; | |||
| 8854 | SDL_Rect cursorPos{ 0, 0, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 8855 | cursor->pos = cursorPos; | |||
| 8856 | cursor->color = makeColor(255, 255, 255, 255 * playerSettings[multiplayer ? 0 : player.playernum].shootmodeCrosshairOpacity / 100.f); | |||
| 8857 | } | |||
| 8858 | } | |||
| 8859 | } | |||
| 8860 | ||||
| 8861 | textPos.x += 40; | |||
| 8862 | textPos.y += 20; | |||
| 8863 | } | |||
| 8864 | ||||
| 8865 | auto glyphPathPressed = Input::inputs[player.playernum].getGlyphPathForBinding("Use", true); | |||
| 8866 | auto glyphPathUnpressed = Input::inputs[player.playernum].getGlyphPathForBinding("Use", false); | |||
| 8867 | auto glyphAdditionalPathPressed = Input::inputs[player.playernum].getGlyphPathForBinding("Defend", true); | |||
| 8868 | auto glyphAdditionalPathUnpressed = Input::inputs[player.playernum].getGlyphPathForBinding("Defend", false); | |||
| 8869 | if ( ticks % 50 < 25 ) | |||
| 8870 | { | |||
| 8871 | glyph->path = glyphPathPressed; | |||
| 8872 | if ( auto imgGet = Image::get(glyph->path.c_str()) ) | |||
| 8873 | { | |||
| 8874 | glyph->disabled = false; | |||
| 8875 | SDL_Rect glyphPos{ textPos.x, textPos.y, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 8876 | glyph->pos = glyphPos; | |||
| 8877 | if ( auto imgGetUnpressed = Image::get(glyphPathUnpressed.c_str()) ) | |||
| 8878 | { | |||
| 8879 | const int unpressedHeight = imgGetUnpressed->getHeight(); | |||
| 8880 | if ( unpressedHeight != glyph->pos.h ) | |||
| 8881 | { | |||
| 8882 | glyph->pos.y -= (glyph->pos.h - unpressedHeight); | |||
| 8883 | } | |||
| 8884 | ||||
| 8885 | if ( unpressedHeight != nominalGlyphHeight ) | |||
| 8886 | { | |||
| 8887 | glyph->pos.y -= (unpressedHeight - nominalGlyphHeight) / 2; | |||
| 8888 | } | |||
| 8889 | } | |||
| 8890 | textPos.x += glyph->pos.w; | |||
| 8891 | } | |||
| 8892 | } | |||
| 8893 | else | |||
| 8894 | { | |||
| 8895 | glyph->path = glyphPathUnpressed; | |||
| 8896 | if ( auto imgGet = Image::get(glyph->path.c_str()) ) | |||
| 8897 | { | |||
| 8898 | glyph->disabled = false; | |||
| 8899 | SDL_Rect glyphPos{ textPos.x, textPos.y, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 8900 | glyph->pos = glyphPos; | |||
| 8901 | textPos.x += glyph->pos.w; | |||
| 8902 | ||||
| 8903 | if ( glyph->pos.h != nominalGlyphHeight ) | |||
| 8904 | { | |||
| 8905 | glyph->pos.y -= (glyph->pos.h - nominalGlyphHeight) / 2; | |||
| 8906 | } | |||
| 8907 | } | |||
| 8908 | } | |||
| 8909 | ||||
| 8910 | textPos.x += skillIconToGlyphPadding; | |||
| 8911 | ||||
| 8912 | if ( Input::inputs[player.playernum].binary("Defend") ) | |||
| 8913 | { | |||
| 8914 | glyphAdditional->path = glyphAdditionalPathUnpressed; | |||
| 8915 | if ( auto imgGet = Image::get(glyphAdditional->path.c_str()) ) | |||
| 8916 | { | |||
| 8917 | glyphAdditional->disabled = false; | |||
| 8918 | SDL_Rect glyphPos{ textPos.x, textPos.y, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 8919 | glyphAdditional->pos = glyphPos; | |||
| 8920 | if ( auto imgGetUnpressed = Image::get(glyphAdditionalPathUnpressed.c_str()) ) | |||
| 8921 | { | |||
| 8922 | const int unpressedHeight = imgGetUnpressed->getHeight(); | |||
| 8923 | if ( unpressedHeight != glyphAdditional->pos.h ) | |||
| 8924 | { | |||
| 8925 | glyphAdditional->pos.y -= (glyphAdditional->pos.h - unpressedHeight); | |||
| 8926 | } | |||
| 8927 | ||||
| 8928 | if ( unpressedHeight != nominalGlyphHeight ) | |||
| 8929 | { | |||
| 8930 | glyphAdditional->pos.y -= (unpressedHeight - nominalGlyphHeight) / 2; | |||
| 8931 | } | |||
| 8932 | } | |||
| 8933 | textPos.x += glyphAdditional->pos.w; | |||
| 8934 | textPos.x += skillIconToGlyphPadding; | |||
| 8935 | } | |||
| 8936 | } | |||
| 8937 | ||||
| 8938 | if ( calloutInteract ) | |||
| 8939 | { | |||
| 8940 | icon->path = "*images/ui/HUD/HUD_Ally_Callout_00.png"; | |||
| 8941 | } | |||
| 8942 | else | |||
| 8943 | { | |||
| 8944 | for ( auto& skill : player.skillSheet.skillSheetData.skillEntries ) | |||
| 8945 | { | |||
| 8946 | if ( skill.skillId == PRO_LEADERSHIP ) | |||
| 8947 | { | |||
| 8948 | if ( skillCapstoneUnlocked(player.playernum, PRO_LEADERSHIP) ) | |||
| 8949 | { | |||
| 8950 | icon->path = skill.skillIconPathLegend; | |||
| 8951 | } | |||
| 8952 | else | |||
| 8953 | { | |||
| 8954 | icon->path = skill.skillIconPath; | |||
| 8955 | } | |||
| 8956 | break; | |||
| 8957 | } | |||
| 8958 | } | |||
| 8959 | } | |||
| 8960 | ||||
| 8961 | if ( auto imgGet = Image::get(icon->path.c_str()) ) | |||
| 8962 | { | |||
| 8963 | icon->disabled = false; | |||
| 8964 | SDL_Rect iconPos{ textPos.x, textPos.y, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 8965 | icon->pos = iconPos; | |||
| 8966 | textPos.x += icon->pos.w + skillIconToGlyphPadding; | |||
| 8967 | } | |||
| 8968 | ||||
| 8969 | ||||
| 8970 | if ( followerInteract && optionSelected == ALLY_CMD_MOVETO_SELECT ) | |||
| 8971 | { | |||
| 8972 | if ( followerMenu.followerToCommand | |||
| 8973 | && (followerMenu.followerToCommand->getMonsterTypeFromSprite() == SENTRYBOT | |||
| 8974 | || followerMenu.followerToCommand->getMonsterTypeFromSprite() == SPELLBOT) | |||
| 8975 | ) | |||
| 8976 | { | |||
| 8977 | text->setDisabled(false); | |||
| 8978 | if ( !glyphAdditional->disabled ) | |||
| 8979 | { | |||
| 8980 | std::string txt = Language::get(4201); | |||
| 8981 | txt += Language::get(3650); | |||
| 8982 | text->setText(txt.c_str()); | |||
| 8983 | } | |||
| 8984 | else | |||
| 8985 | { | |||
| 8986 | text->setText(Language::get(3650)); | |||
| 8987 | } | |||
| 8988 | } | |||
| 8989 | else | |||
| 8990 | { | |||
| 8991 | text->setDisabled(false); | |||
| 8992 | if ( !glyphAdditional->disabled ) | |||
| 8993 | { | |||
| 8994 | std::string txt = Language::get(4201); | |||
| 8995 | txt += Language::get(3039); | |||
| 8996 | text->setText(txt.c_str()); | |||
| 8997 | } | |||
| 8998 | else | |||
| 8999 | { | |||
| 9000 | text->setText(Language::get(3039)); | |||
| 9001 | } | |||
| 9002 | } | |||
| 9003 | } | |||
| 9004 | else | |||
| 9005 | { | |||
| 9006 | if ( followerInteract ) | |||
| 9007 | { | |||
| 9008 | if ( !strcmp(followerMenu.interactText, "") || forceBlankInteractText ) | |||
| 9009 | { | |||
| 9010 | if ( followerMenu.followerToCommand ) | |||
| 9011 | { | |||
| 9012 | int type = followerMenu.followerToCommand->getMonsterTypeFromSprite(); | |||
| 9013 | if ( followerMenu.allowedInteractItems(type) | |||
| 9014 | || followerMenu.allowedInteractFood(type) | |||
| 9015 | || followerMenu.allowedInteractWorld(type) | |||
| 9016 | ) | |||
| 9017 | { | |||
| 9018 | text->setDisabled(false); | |||
| 9019 | text->setText(Language::get(4041)); // "Interact with..." | |||
| 9020 | } | |||
| 9021 | else | |||
| 9022 | { | |||
| 9023 | text->setDisabled(false); | |||
| 9024 | text->setText(Language::get(4042)); // "Attack..." | |||
| 9025 | } | |||
| 9026 | } | |||
| 9027 | else | |||
| 9028 | { | |||
| 9029 | text->setDisabled(false); | |||
| 9030 | text->setText(Language::get(4041)); // "Interact with..." | |||
| 9031 | } | |||
| 9032 | } | |||
| 9033 | else | |||
| 9034 | { | |||
| 9035 | text->setDisabled(false); | |||
| 9036 | text->setText(followerMenu.interactText); | |||
| 9037 | } | |||
| 9038 | } | |||
| 9039 | else if ( calloutInteract ) | |||
| 9040 | { | |||
| 9041 | if ( !strcmp(calloutMenu.interactText, "") || forceBlankInteractText ) | |||
| 9042 | { | |||
| 9043 | text->setDisabled(false); | |||
| 9044 | text->setText(Language::get(4348)); // "Call out..." | |||
| 9045 | } | |||
| 9046 | else | |||
| 9047 | { | |||
| 9048 | text->setDisabled(false); | |||
| 9049 | text->setText(calloutMenu.interactText); | |||
| 9050 | } | |||
| 9051 | } | |||
| 9052 | } | |||
| 9053 | ||||
| 9054 | if ( !glyphAdditional->disabled ) | |||
| 9055 | { | |||
| 9056 | if ( !strstr(text->getText(), Language::get(4201)) ) // no "(ALL) " text | |||
| 9057 | { | |||
| 9058 | glyphAdditional->disabled = true; | |||
| 9059 | textPos.x -= glyphAdditional->pos.w + skillIconToGlyphPadding; | |||
| 9060 | icon->pos.x -= glyphAdditional->pos.w + skillIconToGlyphPadding; | |||
| 9061 | //textPos.x -= icon->pos.w + skillIconToGlyphPadding; | |||
| 9062 | } | |||
| 9063 | } | |||
| 9064 | } | |||
| 9065 | else | |||
| 9066 | { | |||
| 9067 | if ( !player.entity && !player.ghost.isActive() ) | |||
| 9068 | { | |||
| 9069 | cursor->disabled = true; | |||
| 9070 | } | |||
| 9071 | else if ( player.worldUI.bTooltipInView ) | |||
| 9072 | { | |||
| 9073 | cursor->path = "images/system/selectedcursor.png"; | |||
| 9074 | if ( auto imgGet = Image::get(cursor->path.c_str()) ) | |||
| 9075 | { | |||
| 9076 | cursor->disabled = false; | |||
| 9077 | promptPos.x -= (int)imgGet->getWidth() / 2; | |||
| 9078 | promptPos.y -= (int)imgGet->getHeight() / 2; | |||
| 9079 | SDL_Rect cursorPos{ 0, 0, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 9080 | cursor->pos = cursorPos; | |||
| 9081 | cursor->color = makeColor(255, 255, 255, 255 * playerSettings[multiplayer ? 0 : player.playernum].shootmodeCrosshairOpacity / 100.f); | |||
| 9082 | } | |||
| 9083 | ||||
| 9084 | textPos.x += 40; | |||
| 9085 | textPos.y += 20; | |||
| 9086 | ||||
| 9087 | auto glyphPathPressed = Input::inputs[player.playernum].getGlyphPathForBinding("Use", true); | |||
| 9088 | auto glyphPathUnpressed = Input::inputs[player.playernum].getGlyphPathForBinding("Use", false); | |||
| 9089 | if ( ticks % 50 < 25 ) | |||
| 9090 | { | |||
| 9091 | glyph->path = glyphPathPressed; | |||
| 9092 | if ( auto imgGet = Image::get(glyph->path.c_str()) ) | |||
| 9093 | { | |||
| 9094 | glyph->disabled = false; | |||
| 9095 | SDL_Rect glyphPos{ textPos.x, textPos.y, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 9096 | glyph->pos = glyphPos; | |||
| 9097 | if ( auto imgGetUnpressed = Image::get(glyphPathUnpressed.c_str()) ) | |||
| 9098 | { | |||
| 9099 | const int unpressedHeight = imgGetUnpressed->getHeight(); | |||
| 9100 | if ( unpressedHeight != glyph->pos.h ) | |||
| 9101 | { | |||
| 9102 | glyph->pos.y -= (glyph->pos.h - unpressedHeight); | |||
| 9103 | } | |||
| 9104 | ||||
| 9105 | if ( unpressedHeight != nominalGlyphHeight ) | |||
| 9106 | { | |||
| 9107 | glyph->pos.y -= (unpressedHeight - nominalGlyphHeight) / 2; | |||
| 9108 | } | |||
| 9109 | } | |||
| 9110 | textPos.x += glyph->pos.w; | |||
| 9111 | } | |||
| 9112 | } | |||
| 9113 | else | |||
| 9114 | { | |||
| 9115 | glyph->path = glyphPathUnpressed; | |||
| 9116 | if ( auto imgGet = Image::get(glyph->path.c_str()) ) | |||
| 9117 | { | |||
| 9118 | glyph->disabled = false; | |||
| 9119 | SDL_Rect glyphPos{ textPos.x, textPos.y, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 9120 | glyph->pos = glyphPos; | |||
| 9121 | textPos.x += glyph->pos.w; | |||
| 9122 | ||||
| 9123 | if ( glyph->pos.h != nominalGlyphHeight ) | |||
| 9124 | { | |||
| 9125 | glyph->pos.y -= (glyph->pos.h - nominalGlyphHeight) / 2; | |||
| 9126 | } | |||
| 9127 | } | |||
| 9128 | } | |||
| 9129 | textPos.x += skillIconToGlyphPadding; | |||
| 9130 | ||||
| 9131 | if ( usingTinkeringKit ) | |||
| 9132 | { | |||
| 9133 | for ( auto& skill : player.skillSheet.skillSheetData.skillEntries ) | |||
| 9134 | { | |||
| 9135 | if ( skill.skillId == PRO_LOCKPICKING ) | |||
| 9136 | { | |||
| 9137 | if ( skillCapstoneUnlocked(player.playernum, PRO_LOCKPICKING) ) | |||
| 9138 | { | |||
| 9139 | icon->path = skill.skillIconPathLegend; | |||
| 9140 | } | |||
| 9141 | else | |||
| 9142 | { | |||
| 9143 | icon->path = skill.skillIconPath; | |||
| 9144 | } | |||
| 9145 | break; | |||
| 9146 | } | |||
| 9147 | } | |||
| 9148 | ||||
| 9149 | if ( auto imgGet = Image::get(icon->path.c_str()) ) | |||
| 9150 | { | |||
| 9151 | icon->disabled = false; | |||
| 9152 | SDL_Rect iconPos{ textPos.x, textPos.y, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 9153 | icon->pos = iconPos; | |||
| 9154 | textPos.x += icon->pos.w + skillIconToGlyphPadding; | |||
| 9155 | } | |||
| 9156 | } | |||
| 9157 | ||||
| 9158 | text->setDisabled(false); | |||
| 9159 | text->setText(player.worldUI.interactText.c_str()); | |||
| 9160 | } | |||
| 9161 | else | |||
| 9162 | { | |||
| 9163 | if ( useSneakingReticle ) | |||
| 9164 | { | |||
| 9165 | cursor->path = "*#images/system/sneakingcursor.png"; | |||
| 9166 | } | |||
| 9167 | else if ( useBracketsReticle ) | |||
| 9168 | { | |||
| 9169 | cursor->path = "*#images/system/selectedcursor.png"; | |||
| 9170 | } | |||
| 9171 | else | |||
| 9172 | { | |||
| 9173 | cursor->path = getCrosshairPath(); | |||
| 9174 | } | |||
| 9175 | if ( auto imgGet = Image::get(cursor->path.c_str()) ) | |||
| 9176 | { | |||
| 9177 | cursor->disabled = false; | |||
| 9178 | promptPos.x -= (int)imgGet->getWidth() / 2; | |||
| 9179 | promptPos.y -= (int)imgGet->getHeight() / 2; | |||
| 9180 | SDL_Rect cursorPos{ 0, 0, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 9181 | cursor->pos = cursorPos; | |||
| 9182 | cursor->color = makeColor(255, 255, 255, 255 * playerSettings[multiplayer ? 0 : player.playernum].shootmodeCrosshairOpacity / 100.f); | |||
| 9183 | } | |||
| 9184 | ||||
| 9185 | if ( usingTinkeringKit ) | |||
| 9186 | { | |||
| 9187 | if ( player.worldUI.isEnabled() ) | |||
| 9188 | { | |||
| 9189 | textPos.x = cursor->pos.x + cursor->pos.w / 2; | |||
| 9190 | textPos.y = cursor->pos.y + cursor->pos.h / 2; | |||
| 9191 | if ( auto imgGet = Image::get("images/system/selectedcursor.png") ) | |||
| 9192 | { | |||
| 9193 | textPos.x -= (int)imgGet->getWidth() / 2; | |||
| 9194 | textPos.y -= (int)imgGet->getHeight() / 2; | |||
| 9195 | } | |||
| 9196 | ||||
| 9197 | if ( textPos.x < 0 ) | |||
| 9198 | { | |||
| 9199 | promptPos.x += textPos.x; | |||
| 9200 | cursor->pos.x -= textPos.x; | |||
| 9201 | textPos.x = 0; | |||
| 9202 | } | |||
| 9203 | if ( textPos.y < 0 ) | |||
| 9204 | { | |||
| 9205 | promptPos.y += textPos.y; | |||
| 9206 | cursor->pos.y -= textPos.y; | |||
| 9207 | textPos.y = 0; | |||
| 9208 | } | |||
| 9209 | ||||
| 9210 | // skip cursor here, no tooltip in view | |||
| 9211 | textPos.x += 40; | |||
| 9212 | textPos.y += 20; | |||
| 9213 | ||||
| 9214 | auto glyphPathPressed = Input::inputs[player.playernum].getGlyphPathForBinding("Use", true); | |||
| 9215 | auto glyphPathUnpressed = Input::inputs[player.playernum].getGlyphPathForBinding("Use", false); | |||
| 9216 | if ( ticks % 50 < 25 ) | |||
| 9217 | { | |||
| 9218 | glyph->path = glyphPathPressed; | |||
| 9219 | if ( auto imgGet = Image::get(glyph->path.c_str()) ) | |||
| 9220 | { | |||
| 9221 | glyph->disabled = false; | |||
| 9222 | SDL_Rect glyphPos{ textPos.x, textPos.y, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 9223 | glyph->pos = glyphPos; | |||
| 9224 | if ( auto imgGetUnpressed = Image::get(glyphPathUnpressed.c_str()) ) | |||
| 9225 | { | |||
| 9226 | const int unpressedHeight = imgGetUnpressed->getHeight(); | |||
| 9227 | if ( unpressedHeight != glyph->pos.h ) | |||
| 9228 | { | |||
| 9229 | glyph->pos.y -= (glyph->pos.h - unpressedHeight); | |||
| 9230 | } | |||
| 9231 | ||||
| 9232 | if ( unpressedHeight != nominalGlyphHeight ) | |||
| 9233 | { | |||
| 9234 | glyph->pos.y -= (unpressedHeight - nominalGlyphHeight) / 2; | |||
| 9235 | } | |||
| 9236 | } | |||
| 9237 | textPos.x += glyph->pos.w; | |||
| 9238 | } | |||
| 9239 | } | |||
| 9240 | else | |||
| 9241 | { | |||
| 9242 | glyph->path = glyphPathUnpressed; | |||
| 9243 | if ( auto imgGet = Image::get(glyph->path.c_str()) ) | |||
| 9244 | { | |||
| 9245 | glyph->disabled = false; | |||
| 9246 | SDL_Rect glyphPos{ textPos.x, textPos.y, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 9247 | glyph->pos = glyphPos; | |||
| 9248 | textPos.x += glyph->pos.w; | |||
| 9249 | ||||
| 9250 | if ( glyph->pos.h != nominalGlyphHeight ) | |||
| 9251 | { | |||
| 9252 | glyph->pos.y -= (glyph->pos.h - nominalGlyphHeight) / 2; | |||
| 9253 | } | |||
| 9254 | } | |||
| 9255 | } | |||
| 9256 | textPos.x += skillIconToGlyphPadding; | |||
| 9257 | ||||
| 9258 | for ( auto& skill : player.skillSheet.skillSheetData.skillEntries ) | |||
| 9259 | { | |||
| 9260 | if ( skill.skillId == PRO_LOCKPICKING ) | |||
| 9261 | { | |||
| 9262 | if ( skillCapstoneUnlocked(player.playernum, PRO_LOCKPICKING) ) | |||
| 9263 | { | |||
| 9264 | icon->path = skill.skillIconPathLegend; | |||
| 9265 | } | |||
| 9266 | else | |||
| 9267 | { | |||
| 9268 | icon->path = skill.skillIconPath; | |||
| 9269 | } | |||
| 9270 | break; | |||
| 9271 | } | |||
| 9272 | } | |||
| 9273 | ||||
| 9274 | if ( auto imgGet = Image::get(icon->path.c_str()) ) | |||
| 9275 | { | |||
| 9276 | icon->disabled = false; | |||
| 9277 | SDL_Rect iconPos{ textPos.x, textPos.y, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 9278 | icon->pos = iconPos; | |||
| 9279 | textPos.x += icon->pos.w + skillIconToGlyphPadding; | |||
| 9280 | } | |||
| 9281 | ||||
| 9282 | text->setDisabled(false); | |||
| 9283 | text->setText(Language::get(3663)); | |||
| 9284 | } | |||
| 9285 | else | |||
| 9286 | { | |||
| 9287 | textPos.x = cursor->pos.x + 15; | |||
| 9288 | textPos.y = cursor->pos.y + 11; | |||
| 9289 | ||||
| 9290 | text->setDisabled(false); | |||
| 9291 | text->setText(Language::get(3663)); | |||
| 9292 | } | |||
| 9293 | } | |||
| 9294 | } | |||
| 9295 | } | |||
| 9296 | ||||
| 9297 | if ( !text->isDisabled() ) | |||
| 9298 | { | |||
| 9299 | textPos.w = text->getTextObject()->getWidth(); | |||
| 9300 | textPos.h = Font::get(text->getFont())->height() + 8; | |||
| 9301 | textPos.y -= 1; | |||
| 9302 | text->setVJustify(Field::justify_t::CENTER); | |||
| 9303 | text->setSize(textPos); | |||
| 9304 | ||||
| 9305 | promptPos.w = text->getSize().x + text->getSize().w; | |||
| 9306 | promptPos.h = text->getSize().y + text->getSize().h; | |||
| 9307 | } | |||
| 9308 | if ( !glyph->disabled ) | |||
| 9309 | { | |||
| 9310 | promptPos.w = std::max(glyph->pos.x + glyph->pos.w, promptPos.w); | |||
| 9311 | promptPos.h = std::max(glyph->pos.y + glyph->pos.h, promptPos.h); | |||
| 9312 | } | |||
| 9313 | if ( !icon->disabled ) | |||
| 9314 | { | |||
| 9315 | if ( icon->pos.h != nominalGlyphHeight ) | |||
| 9316 | { | |||
| 9317 | icon->pos.y -= (icon->pos.h - nominalGlyphHeight) / 2; | |||
| 9318 | } | |||
| 9319 | ||||
| 9320 | promptPos.w = std::max(icon->pos.x + icon->pos.w, promptPos.w); | |||
| 9321 | promptPos.h = std::max(icon->pos.y + icon->pos.h, promptPos.h); | |||
| 9322 | } | |||
| 9323 | if ( !cursor->disabled ) | |||
| 9324 | { | |||
| 9325 | promptPos.w = std::max(cursor->pos.x + cursor->pos.w, promptPos.w); | |||
| 9326 | promptPos.h = std::max(cursor->pos.y + cursor->pos.h, promptPos.h); | |||
| 9327 | } | |||
| 9328 | ||||
| 9329 | auto prevGlyphPos = glyph->pos; | |||
| 9330 | if ( false && !text->isDisabled() && !glyph->disabled ) | |||
| 9331 | { | |||
| 9332 | if ( CalloutMenu[player.playernum].calloutMenuIsOpen() ) | |||
| 9333 | { | |||
| 9334 | auto glyphPathUnpressed = Input::inputs[player.playernum].getGlyphPathForBinding("Call Out", false); | |||
| 9335 | auto glyphPathPressed = Input::inputs[player.playernum].getGlyphPathForBinding("Call Out", true); | |||
| 9336 | ||||
| 9337 | if ( ticks % 50 < 25 ) | |||
| 9338 | { | |||
| 9339 | glyphCallout->path = glyphPathPressed; | |||
| 9340 | if ( auto imgGet = Image::get(glyphCallout->path.c_str()) ) | |||
| 9341 | { | |||
| 9342 | glyphCallout->disabled = false; | |||
| 9343 | glyphCallout->pos = SDL_Rect{ 0, 0, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 9344 | glyphCallout->pos.y = std::max(icon->pos.y + icon->pos.h - 4, prevGlyphPos.y + prevGlyphPos.h) + 4; | |||
| 9345 | glyphCallout->pos.x = prevGlyphPos.x + prevGlyphPos.w / 2 - glyphCallout->pos.w / 2; | |||
| 9346 | if ( glyphCallout->pos.x % 2 == 1 ) | |||
| 9347 | { | |||
| 9348 | ++glyphCallout->pos.x; | |||
| 9349 | } | |||
| 9350 | if ( auto imgGetUnpressed = Image::get(glyphPathUnpressed.c_str()) ) | |||
| 9351 | { | |||
| 9352 | const int unpressedHeight = imgGetUnpressed->getHeight(); | |||
| 9353 | if ( unpressedHeight != glyphCallout->pos.h ) | |||
| 9354 | { | |||
| 9355 | glyphCallout->pos.y -= (glyphCallout->pos.h - unpressedHeight); | |||
| 9356 | } | |||
| 9357 | ||||
| 9358 | /*if ( unpressedHeight != nominalGlyphHeight ) | |||
| 9359 | { | |||
| 9360 | prevGlyphPos.y -= (unpressedHeight - nominalGlyphHeight) / 2; | |||
| 9361 | }*/ | |||
| 9362 | } | |||
| 9363 | textPos.x += prevGlyphPos.w; | |||
| 9364 | } | |||
| 9365 | } | |||
| 9366 | else | |||
| 9367 | { | |||
| 9368 | glyphCallout->path = glyphPathUnpressed; | |||
| 9369 | if ( auto imgGet = Image::get(glyphCallout->path.c_str()) ) | |||
| 9370 | { | |||
| 9371 | glyphCallout->disabled = false; | |||
| 9372 | glyphCallout->pos = SDL_Rect{ 0, 0, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 9373 | glyphCallout->pos.y = std::max(icon->pos.y + icon->pos.h - 4, prevGlyphPos.y + prevGlyphPos.h) + 4; | |||
| 9374 | glyphCallout->pos.x = prevGlyphPos.x + prevGlyphPos.w / 2 - glyphCallout->pos.w / 2; | |||
| 9375 | if ( glyphCallout->pos.x % 2 == 1 ) | |||
| 9376 | { | |||
| 9377 | ++glyphCallout->pos.x; | |||
| 9378 | } | |||
| 9379 | } | |||
| 9380 | } | |||
| 9381 | ||||
| 9382 | if ( !glyphCallout->disabled ) | |||
| 9383 | { | |||
| 9384 | glyphCallout->color = makeColor(255, 255, 255, 255); | |||
| 9385 | textCallout->setText(Language::get(6049)); | |||
| 9386 | textCallout->setColor(makeColor(255, 255, 255, 255)); | |||
| 9387 | SDL_Rect textPos = text->getSize(); | |||
| 9388 | textPos.x = glyphCallout->pos.x + glyphCallout->pos.w + 4; | |||
| 9389 | textPos.y = glyphCallout->pos.y + 2; | |||
| 9390 | ||||
| 9391 | if ( auto imgGet = Image::get(glyphPathPressed.c_str()) ) | |||
| 9392 | { | |||
| 9393 | if ( imgGet->getHeight() != glyphCallout->pos.h ) | |||
| 9394 | { | |||
| 9395 | textPos.y += (glyphCallout->pos.h - imgGet->getHeight()) / 2; | |||
| 9396 | } | |||
| 9397 | } | |||
| 9398 | if ( glyphCallout->pos.h != nominalGlyphHeight ) | |||
| 9399 | { | |||
| 9400 | textPos.y += (glyphCallout->pos.h - nominalGlyphHeight) / 2; | |||
| 9401 | } | |||
| 9402 | textPos.w = textCallout->getTextObject()->getWidth(); | |||
| 9403 | textCallout->setSize(textPos); | |||
| 9404 | textCallout->setDisabled(false); | |||
| 9405 | ||||
| 9406 | promptPos.w = std::max(textPos.x + textPos.w, promptPos.w); | |||
| 9407 | promptPos.h = std::max(textPos.y + textPos.h, promptPos.h); | |||
| 9408 | promptPos.w = std::max(glyphCallout->pos.x + glyphCallout->pos.w, promptPos.w); | |||
| 9409 | promptPos.h = std::max(glyphCallout->pos.y + glyphCallout->pos.h, promptPos.h); | |||
| 9410 | ||||
| 9411 | prevGlyphPos = glyphCallout->pos; | |||
| 9412 | } | |||
| 9413 | } | |||
| 9414 | } | |||
| 9415 | ||||
| 9416 | if ( player.worldUI.isEnabled() ) | |||
| 9417 | { | |||
| 9418 | if ( !text->isDisabled() && !glyph->disabled && player.worldUI.tooltipsInRange.size() > 1 ) | |||
| 9419 | { | |||
| 9420 | if ( Input::inputs[player.playernum].input("Interact Tooltip Next").type != Input::binding_t::bindtype_t::INVALID ) | |||
| 9421 | { | |||
| 9422 | auto glyphPathUnpressed = Input::inputs[player.playernum].getGlyphPathForBinding("Interact Tooltip Next", false); | |||
| 9423 | auto glyphPathPressed = Input::inputs[player.playernum].getGlyphPathForBinding("Interact Tooltip Next", true); | |||
| 9424 | ||||
| 9425 | if ( ticks % 50 < 25 ) | |||
| 9426 | { | |||
| 9427 | glyphCycle->path = glyphPathPressed; | |||
| 9428 | if ( auto imgGet = Image::get(glyphCycle->path.c_str()) ) | |||
| 9429 | { | |||
| 9430 | glyphCycle->disabled = false; | |||
| 9431 | glyphCycle->pos = SDL_Rect{ 0, 0, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 9432 | glyphCycle->pos.y = prevGlyphPos.y + prevGlyphPos.h + 4; | |||
| 9433 | glyphCycle->pos.x = prevGlyphPos.x + prevGlyphPos.w / 2 - glyphCycle->pos.w / 2; | |||
| 9434 | if ( glyphCycle->pos.x % 2 == 1 ) | |||
| 9435 | { | |||
| 9436 | ++glyphCycle->pos.x; | |||
| 9437 | } | |||
| 9438 | if ( auto imgGetUnpressed = Image::get(glyphPathUnpressed.c_str()) ) | |||
| 9439 | { | |||
| 9440 | const int unpressedHeight = imgGetUnpressed->getHeight(); | |||
| 9441 | if ( unpressedHeight != glyphCycle->pos.h ) | |||
| 9442 | { | |||
| 9443 | glyphCycle->pos.y -= (glyphCycle->pos.h - unpressedHeight); | |||
| 9444 | } | |||
| 9445 | ||||
| 9446 | /*if ( unpressedHeight != nominalGlyphHeight ) | |||
| 9447 | { | |||
| 9448 | glyph->pos.y -= (unpressedHeight - nominalGlyphHeight) / 2; | |||
| 9449 | }*/ | |||
| 9450 | } | |||
| 9451 | textPos.x += prevGlyphPos.w; | |||
| 9452 | } | |||
| 9453 | } | |||
| 9454 | else | |||
| 9455 | { | |||
| 9456 | glyphCycle->path = glyphPathUnpressed; | |||
| 9457 | if ( auto imgGet = Image::get(glyphCycle->path.c_str()) ) | |||
| 9458 | { | |||
| 9459 | glyphCycle->disabled = false; | |||
| 9460 | glyphCycle->pos = SDL_Rect{ 0, 0, (int)imgGet->getWidth(), (int)imgGet->getHeight() }; | |||
| 9461 | glyphCycle->pos.y = prevGlyphPos.y + prevGlyphPos.h + 4; | |||
| 9462 | glyphCycle->pos.x = prevGlyphPos.x + prevGlyphPos.w / 2 - glyphCycle->pos.w / 2; | |||
| 9463 | if ( glyphCycle->pos.x % 2 == 1 ) | |||
| 9464 | { | |||
| 9465 | ++glyphCycle->pos.x; | |||
| 9466 | } | |||
| 9467 | } | |||
| 9468 | } | |||
| 9469 | ||||
| 9470 | if ( !glyphCycle->disabled ) | |||
| 9471 | { | |||
| 9472 | //glyphCycle->pos.x += 16; | |||
| 9473 | //interactPrompt.promptAnim = 1.0; | |||
| 9474 | glyphCycle->color = makeColor(255, 255, 255, 255 * interactPrompt.promptAnim); | |||
| 9475 | textCycle->setText(Language::get(4326)); | |||
| 9476 | textCycle->setColor(makeColor(255, 255, 255, 255 * interactPrompt.promptAnim)); | |||
| 9477 | SDL_Rect textPos = text->getSize(); | |||
| 9478 | textPos.x = glyphCycle->pos.x + glyphCycle->pos.w + 4; | |||
| 9479 | textPos.y = glyphCycle->pos.y + 2; | |||
| 9480 | ||||
| 9481 | if ( auto imgGet = Image::get(glyphPathPressed.c_str()) ) | |||
| 9482 | { | |||
| 9483 | if ( imgGet->getHeight() != glyphCycle->pos.h ) | |||
| 9484 | { | |||
| 9485 | textPos.y += (glyphCycle->pos.h - imgGet->getHeight()) / 2; | |||
| 9486 | } | |||
| 9487 | } | |||
| 9488 | if ( glyphCycle->pos.h != nominalGlyphHeight ) | |||
| 9489 | { | |||
| 9490 | textPos.y += (glyphCycle->pos.h - nominalGlyphHeight) / 2; | |||
| 9491 | } | |||
| 9492 | textPos.w = textCycle->getTextObject()->getWidth(); | |||
| 9493 | glyphCycle->pos.y += 4 * sin(interactPrompt.cycleAnim * PI3.14159265358979323846); | |||
| 9494 | textPos.y += 4 * sin(interactPrompt.cycleAnim * PI3.14159265358979323846); | |||
| 9495 | textCycle->setSize(textPos); | |||
| 9496 | textCycle->setDisabled(false); | |||
| 9497 | ||||
| 9498 | promptPos.w = std::max(textPos.x + textPos.w, promptPos.w); | |||
| 9499 | promptPos.h = std::max(textPos.y + textPos.h, promptPos.h); | |||
| 9500 | promptPos.w = std::max(glyphCycle->pos.x + glyphCycle->pos.w, promptPos.w); | |||
| 9501 | promptPos.h = std::max(glyphCycle->pos.y + glyphCycle->pos.h, promptPos.h); | |||
| 9502 | ||||
| 9503 | if ( interactPrompt.processedOnTick != ticks ) | |||
| 9504 | { | |||
| 9505 | interactPrompt.processedOnTick = ticks; | |||
| 9506 | ++interactPrompt.activeTicks; | |||
| 9507 | } | |||
| 9508 | ||||
| 9509 | if ( interactPrompt.activeTicks > TICKS_PER_SECOND50 / 10 ) | |||
| 9510 | { | |||
| 9511 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 9512 | real_t setpointDiff = fpsScale * std::max(.1, (1.0 - interactPrompt.promptAnim)) / 2.5; | |||
| 9513 | interactPrompt.promptAnim += setpointDiff; | |||
| 9514 | interactPrompt.promptAnim = std::min(1.0, interactPrompt.promptAnim); | |||
| 9515 | } | |||
| 9516 | } | |||
| 9517 | ||||
| 9518 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 9519 | real_t setpointDiff = fpsScale * 0.15; | |||
| 9520 | interactPrompt.cycleAnim += setpointDiff; | |||
| 9521 | interactPrompt.cycleAnim = std::min(1.0, interactPrompt.cycleAnim); | |||
| 9522 | } | |||
| 9523 | } | |||
| 9524 | } | |||
| 9525 | if ( textCycle->isDisabled() ) | |||
| 9526 | { | |||
| 9527 | interactPrompt.promptAnim = 0.0; | |||
| 9528 | interactPrompt.activeTicks = 0; | |||
| 9529 | interactPrompt.cycleAnim = 1.0; | |||
| 9530 | } | |||
| 9531 | worldTooltipFrame->setSize(promptPos); | |||
| 9532 | worldTooltipFrame->setDisabled(false); | |||
| 9533 | } | |||
| 9534 | ||||
| 9535 | std::string actionPromptBackingIconPath00 = ""; | |||
| 9536 | std::string actionPromptBackingIconPath20 = ""; | |||
| 9537 | std::string actionPromptBackingIconPath60 = ""; | |||
| 9538 | std::string actionPromptBackingIconPath100 = ""; | |||
| 9539 | ||||
| 9540 | void createActionPrompts(const int player) | |||
| 9541 | { | |||
| 9542 | auto& hud_t = players[player]->hud; | |||
| 9543 | auto& actionPromptFrame = hud_t.actionPromptsFrame; | |||
| 9544 | actionPromptFrame = hud_t.hudFrame->addFrame("action prompts"); | |||
| 9545 | actionPromptFrame->setHollow(true); | |||
| 9546 | actionPromptFrame->setBorder(0); | |||
| 9547 | actionPromptFrame->setOwner(player); | |||
| 9548 | actionPromptFrame->setSize(SDL_Rect{ 0, 0, hud_t.hudFrame->getSize().w, hud_t.hudFrame->getSize().h }); | |||
| 9549 | actionPromptFrame->setDisabled(true); | |||
| 9550 | ||||
| 9551 | const int iconSize = Player::HUD_t::actionPromptIconSize; | |||
| 9552 | const int glyphSize = 32; | |||
| 9553 | const int iconBackingSize = Player::HUD_t::actionPromptBackingSize; | |||
| 9554 | const int maxWidth = std::max(iconSize, iconBackingSize); | |||
| 9555 | const int maxHeight = std::max(iconSize, iconBackingSize); | |||
| 9556 | const int promptHeight = maxHeight + glyphSize; // vertical space for prompts | |||
| 9557 | ||||
| 9558 | SDL_Rect iconPos{ maxWidth / 2 - iconSize / 2 - 1, | |||
| 9559 | promptHeight - maxHeight / 2 - iconSize / 2 - 1, | |||
| 9560 | iconSize, | |||
| 9561 | iconSize }; | |||
| 9562 | SDL_Rect iconBackingPos{ maxWidth / 2 - iconBackingSize / 2, | |||
| 9563 | promptHeight - maxHeight / 2 - iconBackingSize / 2, | |||
| 9564 | iconBackingSize, | |||
| 9565 | iconBackingSize }; | |||
| 9566 | ||||
| 9567 | const char* promptFont = "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 9568 | ||||
| 9569 | Uint32 iconColor = makeColor(255, 255, 255, Player::HUD_t::actionPromptIconOpacity); | |||
| 9570 | Uint32 iconBackingColor = makeColor(255, 255, 255, Player::HUD_t::actionPromptIconBackingOpacity); | |||
| 9571 | ||||
| 9572 | auto mainHand = actionPromptFrame->addFrame("action mainhand"); | |||
| 9573 | mainHand->setSize(SDL_Rect{ 400, 400, maxWidth, promptHeight }); | |||
| 9574 | mainHand->addImage(iconBackingPos, | |||
| 9575 | iconBackingColor, actionPromptBackingIconPath00.c_str(), "action img backing"); | |||
| 9576 | mainHand->addImage(iconPos, | |||
| 9577 | iconColor, "images/system/white.png", "action img"); | |||
| 9578 | Frame::image_t* glyph = actionPromptFrame->addImage(SDL_Rect{ 0, 0, mainHand->getSize().w, glyphSize }, | |||
| 9579 | 0xFFFFFFFF, "images/system/white.png", "action mainhand glyph"); | |||
| 9580 | glyph->ontop = true; | |||
| 9581 | auto mainHandText = actionPromptFrame->addField("action mainhand text", 64); | |||
| 9582 | mainHandText->setFont(promptFont); | |||
| 9583 | mainHandText->setText(Language::get(5963)); | |||
| 9584 | mainHandText->setHJustify(Field::justify_t::CENTER); | |||
| 9585 | ||||
| 9586 | auto offHand = actionPromptFrame->addFrame("action offhand"); | |||
| 9587 | offHand->setSize(SDL_Rect{ 440, 400, maxWidth, promptHeight }); | |||
| 9588 | offHand->addImage(iconBackingPos, | |||
| 9589 | iconBackingColor, actionPromptBackingIconPath00.c_str(), "action img backing"); | |||
| 9590 | offHand->addImage(iconPos, | |||
| 9591 | iconColor, "images/system/white.png", "action img"); | |||
| 9592 | glyph = actionPromptFrame->addImage(SDL_Rect{ 0, 0, mainHand->getSize().w, glyphSize }, | |||
| 9593 | 0xFFFFFFFF, "images/system/white.png", "action offhand glyph"); | |||
| 9594 | glyph->ontop = true; | |||
| 9595 | auto offHandText = actionPromptFrame->addField("action offhand text", 64); | |||
| 9596 | offHandText->setFont(promptFont); | |||
| 9597 | offHandText->setText(Language::get(5964)); | |||
| 9598 | offHandText->setHJustify(Field::justify_t::CENTER); | |||
| 9599 | ||||
| 9600 | auto magic = actionPromptFrame->addFrame("action magic"); | |||
| 9601 | magic->setSize(SDL_Rect{ 480, 400, maxWidth, promptHeight }); | |||
| 9602 | magic->addImage(iconBackingPos, | |||
| 9603 | iconBackingColor, actionPromptBackingIconPath00.c_str(), "action img backing"); | |||
| 9604 | magic->addImage(iconPos, | |||
| 9605 | iconColor, "images/system/white.png", "action img"); | |||
| 9606 | glyph = actionPromptFrame->addImage(SDL_Rect{ 0, 0, mainHand->getSize().w, glyphSize }, | |||
| 9607 | 0xFFFFFFFF, "images/system/white.png", "action magic glyph"); | |||
| 9608 | glyph->ontop = true; | |||
| 9609 | auto magicText = actionPromptFrame->addField("action magic text", 64); | |||
| 9610 | magicText->setFont(promptFont); | |||
| 9611 | magicText->setText(Language::get(5965)); | |||
| 9612 | magicText->setHJustify(Field::justify_t::CENTER); | |||
| 9613 | ||||
| 9614 | auto sneak = actionPromptFrame->addFrame("action sneak"); | |||
| 9615 | sneak->setSize(SDL_Rect{ 480, 400, maxWidth, promptHeight }); | |||
| 9616 | sneak->addImage(iconBackingPos, | |||
| 9617 | iconBackingColor, actionPromptBackingIconPath00.c_str(), "action img backing"); | |||
| 9618 | sneak->addImage(iconPos, | |||
| 9619 | iconColor, "images/system/white.png", "action img"); | |||
| 9620 | glyph = actionPromptFrame->addImage(SDL_Rect{ 0, 0, mainHand->getSize().w, glyphSize }, | |||
| 9621 | 0xFFFFFFFF, "images/system/white.png", "action sneak glyph"); | |||
| 9622 | glyph->ontop = true; | |||
| 9623 | auto sneakText = actionPromptFrame->addField("action sneak text", 64); | |||
| 9624 | sneakText->setFont(promptFont); | |||
| 9625 | sneakText->setText(Language::get(5964)); | |||
| 9626 | sneakText->setHJustify(Field::justify_t::CENTER); | |||
| 9627 | } | |||
| 9628 | ||||
| 9629 | void drawActionPromptCooldownCallback(const Widget& widget, SDL_Rect rect) | |||
| 9630 | { | |||
| 9631 | const int player = widget.getOwner(); | |||
| 9632 | ||||
| 9633 | const Frame* parent = static_cast<const Frame*>(widget.getParent()); | |||
| 9634 | { | |||
| 9635 | SDL_Rect drawRect = rect; | |||
| 9636 | drawRect.x += 22; | |||
| 9637 | drawRect.y += 22; | |||
| 9638 | drawRect.w = 44; | |||
| 9639 | drawRect.h = 44; | |||
| 9640 | real_t opacity = 192; | |||
| 9641 | if ( parent && parent->getOpacity() < 100.0 ) | |||
| 9642 | { | |||
| 9643 | opacity *= parent->getOpacity() / 100.0; | |||
| 9644 | } | |||
| 9645 | const auto& ghost = players[player]->ghost; | |||
| 9646 | int prompt = reinterpret_cast<intptr_t>(widget.getUserData()) - 1; | |||
| 9647 | real_t cooldownProgress = 0.0; | |||
| 9648 | bool errorFlash = false; | |||
| 9649 | int actionPoints = 0; | |||
| 9650 | switch ( static_cast<Player::HUD_t::ActionPrompts>(prompt) ) | |||
| 9651 | { | |||
| 9652 | case Player::HUD_t::ACTION_PROMPT_MAGIC: | |||
| 9653 | cooldownProgress = (ghost.cooldownTeleport / (real_t)ghost.cooldownTeleportDelay); | |||
| 9654 | if ( ghost.errorFlashTeleportTicks > 0 && (Player::Ghost_t::errorFlashTicks - ghost.errorFlashTeleportTicks) % 20 < 10 ) | |||
| 9655 | { | |||
| 9656 | errorFlash = true; | |||
| 9657 | } | |||
| 9658 | break; | |||
| 9659 | case Player::HUD_t::ACTION_PROMPT_OFFHAND: | |||
| 9660 | if ( ghost.pushPoints > 0 ) | |||
| 9661 | { | |||
| 9662 | cooldownProgress = 0.0; | |||
| 9663 | } | |||
| 9664 | else | |||
| 9665 | { | |||
| 9666 | cooldownProgress = (ghost.cooldownPush / (real_t)ghost.cooldownPushDelay); | |||
| 9667 | } | |||
| 9668 | actionPoints = ghost.pushPoints; | |||
| 9669 | if ( ghost.errorFlashPushTicks > 0 && (Player::Ghost_t::errorFlashTicks - ghost.errorFlashPushTicks) % 20 < 10 ) | |||
| 9670 | { | |||
| 9671 | errorFlash = true; | |||
| 9672 | } | |||
| 9673 | break; | |||
| 9674 | case Player::HUD_t::ACTION_PROMPT_MAINHAND: | |||
| 9675 | cooldownProgress = (ghost.cooldownChill / (real_t)ghost.cooldownChillDelay); | |||
| 9676 | if ( ghost.errorFlashChillTicks > 0 && (Player::Ghost_t::errorFlashTicks - ghost.errorFlashChillTicks) % 20 < 10 ) | |||
| 9677 | { | |||
| 9678 | errorFlash = true; | |||
| 9679 | } | |||
| 9680 | break; | |||
| 9681 | case Player::HUD_t::ACTION_PROMPT_SNEAK: | |||
| 9682 | break; | |||
| 9683 | default: | |||
| 9684 | break; | |||
| 9685 | } | |||
| 9686 | if ( cooldownProgress > 0.0 ) | |||
| 9687 | { | |||
| 9688 | if ( errorFlash ) | |||
| 9689 | { | |||
| 9690 | drawClockwiseSquareMesh("images/ui/HUD/HUD_ActionPromptBacking00_02_Cooldown.png", | |||
| 9691 | cooldownProgress, | |||
| 9692 | drawRect, makeColor(255, 255, 255, opacity)); | |||
| 9693 | } | |||
| 9694 | else | |||
| 9695 | { | |||
| 9696 | Uint8 r, g, b, a; | |||
| 9697 | getColor(hudColors.characterSheetRed, &r, &g, &b, &a); | |||
| 9698 | drawClockwiseSquareMesh("images/ui/HUD/HUD_ActionPromptBacking00_02_Cooldown.png", | |||
| 9699 | cooldownProgress, | |||
| 9700 | drawRect, makeColor(r, g, b, opacity)); | |||
| 9701 | } | |||
| 9702 | } | |||
| 9703 | /*if ( actionPoints > 0 ) | |||
| 9704 | { | |||
| 9705 | std::string str = std::to_string(actionPoints); | |||
| 9706 | if ( auto textGet = Text::get(str.c_str(), smallfont_outline, makeColorRGB(255, 255, 255), 0) ) | |||
| 9707 | { | |||
| 9708 | textGet->drawColor(SDL_Rect{ 0,0,0,0 }, SDL_Rect{ drawRect.x - 6, drawRect.y + 1, 0, 0 }, | |||
| 9709 | SDL_Rect{ 0, 0, Frame::virtualScreenX, Frame::virtualScreenY }, | |||
| 9710 | makeColor(255, 255, 255, 255)); | |||
| 9711 | } | |||
| 9712 | }*/ | |||
| 9713 | } | |||
| 9714 | } | |||
| 9715 | ||||
| 9716 | int Player::HUD_t::actionPromptOffsetX = 280; | |||
| 9717 | int Player::HUD_t::actionPromptOffsetXGhostPrompts = 140; | |||
| 9718 | int Player::HUD_t::actionPromptOffsetY = 22; | |||
| 9719 | int Player::HUD_t::actionPromptBackingSize = 44; | |||
| 9720 | int Player::HUD_t::actionPromptIconSize = 32; | |||
| 9721 | int Player::HUD_t::actionPromptIconOpacity = 255; | |||
| 9722 | int Player::HUD_t::actionPromptIconBackingOpacity = 255; | |||
| 9723 | static ConsoleVariable<bool> disableActionPrompts( | |||
| 9724 | "/disableactionprompts", false, "Disable action prompts in HUD"); | |||
| 9725 | void Player::HUD_t::updateActionPrompts() | |||
| 9726 | { | |||
| 9727 | if ( !hudFrame ) | |||
| 9728 | { | |||
| 9729 | return; | |||
| 9730 | } | |||
| 9731 | ||||
| 9732 | if ( !actionPromptsFrame ) | |||
| 9733 | { | |||
| 9734 | createActionPrompts(player.playernum); | |||
| 9735 | if ( !actionPromptsFrame ) | |||
| 9736 | { | |||
| 9737 | return; | |||
| 9738 | } | |||
| 9739 | } | |||
| 9740 | ||||
| 9741 | ||||
| 9742 | int playercount = 0; | |||
| 9743 | for (int c = 0; c < MAXPLAYERS4; ++c) { | |||
| 9744 | if (!client_disconnected[c] && players[c]->isLocalPlayer()) { | |||
| 9745 | ++playercount; | |||
| 9746 | } | |||
| 9747 | } | |||
| 9748 | ||||
| 9749 | bool ghostPrompts = player.ghost.isActive(); | |||
| 9750 | static ConsoleVariable<int> actionPromptCompactHeightY("/actionpromptcompactheighty", 16); | |||
| 9751 | bShowActionPrompts = *disableActionPrompts; | |||
| 9752 | bShortHPMPForActionBars = false; | |||
| 9753 | ||||
| 9754 | if ( playercount == 2 && !*MainMenu::vertical_splitscreen && !ghostPrompts | |||
| 9755 | && !*disableActionPrompts && *MainMenu::clipped_splitscreen ) | |||
| 9756 | { | |||
| 9757 | bShortHPMPForActionBars = true; | |||
| 9758 | } | |||
| 9759 | ||||
| 9760 | if ( playercount > 2 | |||
| 9761 | || (playercount == 2 | |||
| 9762 | && (*MainMenu::vertical_splitscreen | |||
| 9763 | /*|| !player.shootmode */ | |||
| 9764 | || (!player.shootmode && player.hud.compactLayoutMode == Player::HUD_t::COMPACT_LAYOUT_CHARSHEET) | |||
| 9765 | || (!player.hotbar.useHotbarFaceMenu && *MainMenu::clipped_splitscreen))) | |||
| 9766 | || *disableActionPrompts ) | |||
| 9767 | { | |||
| 9768 | if ( !ghostPrompts ) | |||
| 9769 | { | |||
| 9770 | actionPromptsFrame->setDisabled(true); | |||
| 9771 | bShowActionPrompts = false; | |||
| 9772 | return; | |||
| 9773 | } | |||
| 9774 | } | |||
| 9775 | actionPromptsFrame->setDisabled(false); | |||
| 9776 | actionPromptsFrame->setSize(SDL_Rect{ 0, 0, hudFrame->getSize().w, hudFrame->getSize().h }); | |||
| 9777 | ||||
| 9778 | bool tempHideActionPrompts = false; | |||
| 9779 | bool fadeOut = false; | |||
| 9780 | if ( ghostPrompts ) | |||
| 9781 | { | |||
| 9782 | if ( player.bUseCompactGUIHeight() && CalloutMenu[player.playernum].calloutMenuIsOpen() && !CalloutMenu[player.playernum].selectMoveTo ) | |||
| 9783 | { | |||
| 9784 | tempHideActionPrompts = true; | |||
| 9785 | } | |||
| 9786 | } | |||
| 9787 | ||||
| 9788 | if ( tempHideActionPrompts ) | |||
| 9789 | { | |||
| 9790 | if ( fadeOut ) | |||
| 9791 | { | |||
| 9792 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 9793 | real_t setpointDiff = fpsScale * std::max(.1, (1.0 - animHideActionPrompts)) / 2.5; | |||
| 9794 | animHideActionPrompts += setpointDiff; | |||
| 9795 | animHideActionPrompts = std::min(1.0, animHideActionPrompts); | |||
| 9796 | } | |||
| 9797 | else | |||
| 9798 | { | |||
| 9799 | animHideActionPrompts = 1.0; | |||
| 9800 | } | |||
| 9801 | } | |||
| 9802 | else | |||
| 9803 | { | |||
| 9804 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 9805 | real_t setpointDiff = fpsScale * std::max(.1, (animHideActionPrompts)) / 2.5; | |||
| 9806 | animHideActionPrompts -= setpointDiff; | |||
| 9807 | animHideActionPrompts = std::max(0.0, animHideActionPrompts); | |||
| 9808 | } | |||
| 9809 | ||||
| 9810 | actionPromptsFrame->setInheritParentFrameOpacity(false); | |||
| 9811 | real_t opacity = 1.0; | |||
| 9812 | if ( auto parent = actionPromptsFrame->getParent() ) | |||
| 9813 | { | |||
| 9814 | opacity *= actionPromptsFrame->getParent()->getOpacity() / 100.0; | |||
| 9815 | } | |||
| 9816 | actionPromptsFrame->setOpacity((opacity - animHideActionPrompts) * 100.0); | |||
| 9817 | ||||
| 9818 | const int iconSize = Player::HUD_t::actionPromptIconSize; | |||
| 9819 | const int glyphSize = 32; | |||
| 9820 | const int iconBackingSize = Player::HUD_t::actionPromptBackingSize; | |||
| 9821 | const int maxWidth = std::max(iconSize, iconBackingSize); | |||
| 9822 | const int maxHeight = std::max(iconSize, iconBackingSize); | |||
| 9823 | const int promptHeight = maxHeight + glyphSize; // vertical space for prompts | |||
| 9824 | ||||
| 9825 | SDL_Rect iconPos{ maxWidth / 2 - iconSize / 2 - 0, | |||
| 9826 | maxHeight / 2 - iconSize / 2 - 0, | |||
| 9827 | iconSize, | |||
| 9828 | iconSize }; | |||
| 9829 | SDL_Rect iconBackingPos{ maxWidth / 2 - iconBackingSize / 2, | |||
| 9830 | maxHeight / 2 - iconBackingSize / 2, | |||
| 9831 | iconBackingSize, | |||
| 9832 | iconBackingSize }; | |||
| 9833 | ||||
| 9834 | struct PromptInfo { | |||
| 9835 | std::string name; | |||
| 9836 | ActionPrompts promptType; | |||
| 9837 | std::string inputName; | |||
| 9838 | }; | |||
| 9839 | ||||
| 9840 | std::vector<PromptInfo> allPrompts; | |||
| 9841 | const std::string blockBinding = Input::inputs[player.playernum].binding("Defend"); | |||
| 9842 | const std::string sneakBinding = Input::inputs[player.playernum].binding("Sneak"); | |||
| 9843 | bool sneakingSeparateFromBlock = false;// blockBinding != sneakBinding; | |||
| 9844 | if ( ghostPrompts ) | |||
| 9845 | { | |||
| 9846 | sneakingSeparateFromBlock = true; | |||
| 9847 | allPrompts.emplace_back(PromptInfo{ "action sneak", ACTION_PROMPT_SNEAK, "Sneak" }); | |||
| 9848 | allPrompts.emplace_back(PromptInfo{ "action offhand", ACTION_PROMPT_OFFHAND, "Use" }); | |||
| 9849 | allPrompts.emplace_back(PromptInfo{ "action magic", ACTION_PROMPT_MAGIC, "Cast Spell" }); | |||
| 9850 | allPrompts.emplace_back(PromptInfo{ "action mainhand", ACTION_PROMPT_MAINHAND, "Attack" }); | |||
| 9851 | } | |||
| 9852 | else if ( sneakingSeparateFromBlock ) | |||
| 9853 | { | |||
| 9854 | allPrompts.emplace_back(PromptInfo{ "action offhand", ACTION_PROMPT_OFFHAND, "Defend" }); | |||
| 9855 | allPrompts.emplace_back(PromptInfo{ "action sneak", ACTION_PROMPT_SNEAK, "Sneak" }); | |||
| 9856 | allPrompts.emplace_back(PromptInfo{ "action magic", ACTION_PROMPT_MAGIC, "Cast Spell" }); | |||
| 9857 | allPrompts.emplace_back(PromptInfo{ "action mainhand", ACTION_PROMPT_MAINHAND, "Attack" }); | |||
| 9858 | } | |||
| 9859 | else | |||
| 9860 | { | |||
| 9861 | allPrompts.emplace_back(PromptInfo{ "action offhand", ACTION_PROMPT_OFFHAND, "Defend" }); | |||
| 9862 | allPrompts.emplace_back(PromptInfo{ "action sneak", ACTION_PROMPT_SNEAK, "Sneak" }); | |||
| 9863 | allPrompts.emplace_back(PromptInfo{ "action magic", ACTION_PROMPT_MAGIC, "Cast Spell" }); | |||
| 9864 | allPrompts.emplace_back(PromptInfo{ "action mainhand", ACTION_PROMPT_MAINHAND, "Attack" }); | |||
| 9865 | } | |||
| 9866 | ||||
| 9867 | Uint32 iconBackingColor = makeColor(255, 255, 255, Player::HUD_t::actionPromptIconBackingOpacity); | |||
| 9868 | Uint32 iconColor = makeColor(255, 255, 255, Player::HUD_t::actionPromptIconOpacity); | |||
| 9869 | Uint32 iconFadedColor = makeColor(255, 255, 255, Player::HUD_t::actionPromptIconOpacity * .5); | |||
| 9870 | Uint32 iconFadedBackingColor = makeColor(255, 255, 255, Player::HUD_t::actionPromptIconBackingOpacity * .5); | |||
| 9871 | ||||
| 9872 | int index = 0; | |||
| 9873 | for ( auto& promptInfo : allPrompts ) | |||
| 9874 | { | |||
| 9875 | if ( auto prompt = actionPromptsFrame->findFrame(promptInfo.name.c_str()) ) | |||
| 9876 | { | |||
| 9877 | prompt->setDisabled(false); | |||
| 9878 | ||||
| 9879 | std::string glyphName = promptInfo.name + " glyph"; | |||
| 9880 | auto img = prompt->findImage("action img"); | |||
| 9881 | auto glyph = actionPromptsFrame->findImage(glyphName.c_str()); | |||
| 9882 | auto imgBacking = prompt->findImage("action img backing"); | |||
| 9883 | ||||
| 9884 | SDL_Rect promptPos = prompt->getSize(); | |||
| 9885 | promptPos.w = maxWidth; | |||
| 9886 | promptPos.h = promptHeight; | |||
| 9887 | int actionPromptOffsetXTotal = actionPromptOffsetX; | |||
| 9888 | prompt->setDrawCallback(nullptr); | |||
| 9889 | prompt->setUserData(nullptr); | |||
| 9890 | if ( ghostPrompts ) | |||
| 9891 | { | |||
| 9892 | actionPromptOffsetXTotal = actionPromptOffsetXGhostPrompts; | |||
| 9893 | prompt->setUserData((void*)(intptr_t)(promptInfo.promptType + 1)); | |||
| 9894 | prompt->setDrawCallback([](const Widget& widget, SDL_Rect rect) { | |||
| 9895 | drawActionPromptCooldownCallback(widget, rect); | |||
| 9896 | }); | |||
| 9897 | } | |||
| 9898 | else if ( !player.hotbar.useHotbarFaceMenu ) | |||
| 9899 | { | |||
| 9900 | actionPromptOffsetXTotal += 22; | |||
| 9901 | } | |||
| 9902 | switch ( index ) | |||
| 9903 | { | |||
| 9904 | case 0: // to the left of hotbar | |||
| 9905 | promptPos.x = hudFrame->getSize().w / 2 - actionPromptOffsetXTotal; | |||
| 9906 | break; | |||
| 9907 | case 1: // to the left after the previous | |||
| 9908 | promptPos.x = hudFrame->getSize().w / 2 - actionPromptOffsetXTotal; | |||
| 9909 | promptPos.x -= 16; | |||
| 9910 | promptPos.x -= promptPos.w; | |||
| 9911 | break; | |||
| 9912 | case 2: // to the right of hotbar | |||
| 9913 | promptPos.x = hudFrame->getSize().w / 2 + actionPromptOffsetXTotal; | |||
| 9914 | promptPos.x -= promptPos.w; | |||
| 9915 | break; | |||
| 9916 | case 3: // to the right after the previous | |||
| 9917 | promptPos.x = hudFrame->getSize().w / 2 + actionPromptOffsetXTotal; | |||
| 9918 | promptPos.x += 16; | |||
| 9919 | break; | |||
| 9920 | default: | |||
| 9921 | break; | |||
| 9922 | } | |||
| 9923 | promptPos.y = hudFrame->getSize().h + player.hotbar.getHotbarStartY2() - promptPos.h; | |||
| 9924 | promptPos.y += maxHeight / 2; | |||
| 9925 | promptPos.y += actionPromptOffsetY; | |||
| 9926 | if ( player.bUseCompactGUIHeight() ) | |||
| 9927 | { | |||
| 9928 | promptPos.y += *actionPromptCompactHeightY; | |||
| 9929 | } | |||
| 9930 | prompt->setSize(promptPos); | |||
| 9931 | ||||
| 9932 | img->pos = iconPos; | |||
| 9933 | imgBacking->pos = iconBackingPos; | |||
| 9934 | img->color = iconColor; | |||
| 9935 | imgBacking->color = iconBackingColor; | |||
| 9936 | ||||
| 9937 | Field* promptText = nullptr; | |||
| 9938 | switch ( promptInfo.promptType ) | |||
| 9939 | { | |||
| 9940 | case ACTION_PROMPT_MAINHAND: | |||
| 9941 | promptText = actionPromptsFrame->findField("action mainhand text"); | |||
| 9942 | break; | |||
| 9943 | case ACTION_PROMPT_OFFHAND: | |||
| 9944 | promptText = actionPromptsFrame->findField("action offhand text"); | |||
| 9945 | break; | |||
| 9946 | case ACTION_PROMPT_MAGIC: | |||
| 9947 | promptText = actionPromptsFrame->findField("action magic text"); | |||
| 9948 | break; | |||
| 9949 | case ACTION_PROMPT_SNEAK: | |||
| 9950 | promptText = actionPromptsFrame->findField("action sneak text"); | |||
| 9951 | break; | |||
| 9952 | default: | |||
| 9953 | break; | |||
| 9954 | } | |||
| 9955 | ||||
| 9956 | if ( promptInfo.promptType == ACTION_PROMPT_SNEAK && !sneakingSeparateFromBlock ) | |||
| 9957 | { | |||
| 9958 | prompt->setDisabled(true); | |||
| 9959 | promptText->setDisabled(true); | |||
| 9960 | glyph->disabled = true; | |||
| 9961 | ++index; | |||
| 9962 | continue; | |||
| 9963 | } | |||
| 9964 | ||||
| 9965 | std::string textForPrompt = ""; | |||
| 9966 | int skillForPrompt = getActionIconForPlayer(promptInfo.promptType, textForPrompt); | |||
| 9967 | if ( promptInfo.promptType == ACTION_PROMPT_OFFHAND && sneakingSeparateFromBlock && !ghostPrompts | |||
| 9968 | && skillForPrompt == PRO_STEALTH ) | |||
| 9969 | { | |||
| 9970 | // offhand wants to display sneak - redundant, hide this prompt | |||
| 9971 | prompt->setDisabled(true); | |||
| 9972 | promptText->setDisabled(true); | |||
| 9973 | glyph->disabled = true; | |||
| 9974 | ++index; | |||
| 9975 | continue; | |||
| 9976 | } | |||
| 9977 | ||||
| 9978 | if ( player.shootmode || player.gui_mode == GUI_MODE_FOLLOWERMENU | |||
| 9979 | || player.gui_mode == GUI_MODE_SIGN | |||
| 9980 | || player.gui_mode == GUI_MODE_CALLOUT ) | |||
| 9981 | { | |||
| 9982 | promptText->setDisabled(true); | |||
| 9983 | } | |||
| 9984 | else | |||
| 9985 | { | |||
| 9986 | promptText->setDisabled(false); | |||
| 9987 | promptText->setText(textForPrompt.c_str()); | |||
| 9988 | SDL_Rect textPos; | |||
| 9989 | auto textGetLongestLine = Text::get(promptText->getLongestLine().c_str(), | |||
| 9990 | promptText->getFont(), | |||
| 9991 | promptText->getTextColor(), | |||
| 9992 | promptText->getOutlineColor()); | |||
| 9993 | textPos.w = textGetLongestLine->getWidth(); | |||
| 9994 | textPos.h = promptText->getNumTextLines() * Font::get(promptText->getFont())->height(); | |||
| 9995 | textPos.x = promptPos.x + promptPos.w / 2 - textPos.w / 2; | |||
| 9996 | //textPos.y = promptPos.y + imgBacking->pos.y - textPos.h - 4; -- top aligned | |||
| 9997 | textPos.y = promptPos.y + imgBacking->pos.y + imgBacking->pos.h + 1; | |||
| 9998 | promptText->setSize(textPos); | |||
| 9999 | } | |||
| 10000 | ||||
| 10001 | std::string skillImg = ""; | |||
| 10002 | if ( skillForPrompt >= 0 && skillForPrompt < NUMPROFICIENCIES ) | |||
| 10003 | { | |||
| 10004 | for ( auto& skill : player.skillSheet.skillSheetData.skillEntries ) | |||
| 10005 | { | |||
| 10006 | if ( skill.skillId == skillForPrompt ) | |||
| 10007 | { | |||
| 10008 | if ( skillCapstoneUnlocked(player.playernum, skillForPrompt) ) | |||
| 10009 | { | |||
| 10010 | skillImg = skill.skillIconPathLegend32px; | |||
| 10011 | } | |||
| 10012 | else | |||
| 10013 | { | |||
| 10014 | skillImg = skill.skillIconPath32px; | |||
| 10015 | } | |||
| 10016 | break; | |||
| 10017 | } | |||
| 10018 | } | |||
| 10019 | if ( stats[player.playernum]->getModifiedProficiency(skillForPrompt) >= SKILL_LEVEL_LEGENDARY ) | |||
| 10020 | { | |||
| 10021 | imgBacking->path = actionPromptBackingIconPath100; | |||
| 10022 | } | |||
| 10023 | else if ( stats[player.playernum]->getModifiedProficiency(skillForPrompt) >= SKILL_LEVEL_EXPERT ) | |||
| 10024 | { | |||
| 10025 | imgBacking->path = actionPromptBackingIconPath60; | |||
| 10026 | } | |||
| 10027 | else if ( stats[player.playernum]->getModifiedProficiency(skillForPrompt) >= SKILL_LEVEL_BASIC ) | |||
| 10028 | { | |||
| 10029 | imgBacking->path = actionPromptBackingIconPath20; | |||
| 10030 | } | |||
| 10031 | else | |||
| 10032 | { | |||
| 10033 | imgBacking->path = actionPromptBackingIconPath00; | |||
| 10034 | } | |||
| 10035 | } | |||
| 10036 | else if ( ghostPrompts ) | |||
| 10037 | { | |||
| 10038 | imgBacking->path = actionPromptBackingIconPath00; | |||
| 10039 | switch ( promptInfo.promptType ) | |||
| 10040 | { | |||
| 10041 | case ACTION_PROMPT_MAGIC: | |||
| 10042 | skillImg = "*images/ui/HUD/HUD_Ghost_Haunt.png"; | |||
| 10043 | img->pos.x -= 2; | |||
| 10044 | img->pos.y -= 2; | |||
| 10045 | img->pos.w = 36; | |||
| 10046 | img->pos.h = 36; | |||
| 10047 | break; | |||
| 10048 | case ACTION_PROMPT_MAINHAND: | |||
| 10049 | skillImg = "*images/ui/HUD/HUD_Ghost_Chill.png"; | |||
| 10050 | img->pos.x -= 2; | |||
| 10051 | img->pos.y -= 2; | |||
| 10052 | img->pos.w = 36; | |||
| 10053 | img->pos.h = 36; | |||
| 10054 | break; | |||
| 10055 | case ACTION_PROMPT_OFFHAND: | |||
| 10056 | skillImg = "*images/ui/HUD/HUD_Ghost_Push.png"; | |||
| 10057 | img->pos.x -= 2; | |||
| 10058 | img->pos.y -= 2; | |||
| 10059 | img->pos.w = 36; | |||
| 10060 | img->pos.h = 36; | |||
| 10061 | break; | |||
| 10062 | case ACTION_PROMPT_SNEAK: | |||
| 10063 | for ( auto& skill : player.skillSheet.skillSheetData.skillEntries ) | |||
| 10064 | { | |||
| 10065 | if ( skill.skillId == PRO_STEALTH ) | |||
| 10066 | { | |||
| 10067 | skillImg = skill.skillIconPath32px; | |||
| 10068 | break; | |||
| 10069 | } | |||
| 10070 | } | |||
| 10071 | break; | |||
| 10072 | default: | |||
| 10073 | break; | |||
| 10074 | } | |||
| 10075 | } | |||
| 10076 | if ( skillImg == "" ) | |||
| 10077 | { | |||
| 10078 | prompt->setDisabled(true); | |||
| 10079 | } | |||
| 10080 | else | |||
| 10081 | { | |||
| 10082 | prompt->setDisabled(false); | |||
| 10083 | img->path = skillImg; | |||
| 10084 | if ( img->path[0] != '*' ) | |||
| 10085 | { | |||
| 10086 | img->path = '*' + img->path; | |||
| 10087 | } | |||
| 10088 | } | |||
| 10089 | ||||
| 10090 | bool pressed = false; | |||
| 10091 | /*if ( skillForPrompt == PRO_SHIELD && stats[player.playernum]->defending ) | |||
| 10092 | { | |||
| 10093 | pressed = true; | |||
| 10094 | } | |||
| 10095 | if ( skillForPrompt == PRO_STEALTH && !stats[player.playernum]->defending | |||
| 10096 | && stats[player.playernum]->sneaking ) | |||
| 10097 | { | |||
| 10098 | pressed = true; | |||
| 10099 | }*/ | |||
| 10100 | ||||
| 10101 | std::string bindingName = promptInfo.inputName.c_str(); | |||
| 10102 | if ( !ghostPrompts ) | |||
| 10103 | { | |||
| 10104 | if ( skillForPrompt == PRO_STEALTH && promptInfo.promptType == ACTION_PROMPT_OFFHAND ) | |||
| 10105 | { | |||
| 10106 | bindingName = "Sneak"; | |||
| 10107 | } | |||
| 10108 | } | |||
| 10109 | glyph->path = Input::inputs[player.playernum].getGlyphPathForBinding(bindingName.c_str(), pressed); | |||
| 10110 | glyph->disabled = prompt->isDisabled(); | |||
| 10111 | if ( !player.shootmode || player.gui_mode == GUI_MODE_FOLLOWERMENU | |||
| 10112 | || player.gui_mode == GUI_MODE_SIGN | |||
| 10113 | || player.gui_mode == GUI_MODE_CALLOUT ) | |||
| 10114 | { | |||
| 10115 | glyph->disabled = true; | |||
| 10116 | } | |||
| 10117 | else if ( inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 10118 | { | |||
| 10119 | glyph->disabled = false; | |||
| 10120 | } | |||
| 10121 | else | |||
| 10122 | { | |||
| 10123 | glyph->disabled = false; | |||
| 10124 | } | |||
| 10125 | if ( auto imgGet = Image::get(glyph->path.c_str()) ) | |||
| 10126 | { | |||
| 10127 | glyph->pos.w = (int)imgGet->getWidth(); | |||
| 10128 | glyph->pos.h = (int)imgGet->getHeight(); | |||
| 10129 | } | |||
| 10130 | glyph->pos.x = prompt->getSize().x + prompt->getSize().w / 2 - glyph->pos.w / 2; // center the x for the glyph | |||
| 10131 | int glyphToImgPadY = 0; | |||
| 10132 | if ( Input::inputs[player.playernum].input(bindingName.c_str()).type == Input::binding_t::bindtype_t::MOUSE_BUTTON ) | |||
| 10133 | { | |||
| 10134 | glyphToImgPadY += 4; | |||
| 10135 | } | |||
| 10136 | int pressedOffset = 0; | |||
| 10137 | /*if ( pressed ) | |||
| 10138 | { | |||
| 10139 | if ( auto imgGet = Image::get(Input::inputs[player.playernum].getGlyphPathForBinding(promptInfo.inputName.c_str()).c_str()) ) | |||
| 10140 | { | |||
| 10141 | int unpressedHeight = (int)imgGet->getHeight(); | |||
| 10142 | if ( glyph->pos.h != unpressedHeight ) | |||
| 10143 | { | |||
| 10144 | pressedOffset = (unpressedHeight - glyph->pos.h); | |||
| 10145 | } | |||
| 10146 | } | |||
| 10147 | }*/ | |||
| 10148 | glyph->pos.y = prompt->getSize().y + img->pos.y + img->pos.h - glyphToImgPadY + pressedOffset; // just above the skill img with some padding | |||
| 10149 | ||||
| 10150 | if ( !ghostPrompts ) | |||
| 10151 | { | |||
| 10152 | if ( promptInfo.promptType == ACTION_PROMPT_SNEAK ) | |||
| 10153 | { | |||
| 10154 | if ( !(!stats[player.playernum]->defending && stats[player.playernum]->sneaking) ) | |||
| 10155 | { | |||
| 10156 | //glyph->disabled = true; | |||
| 10157 | img->color = iconFadedColor; | |||
| 10158 | //imgBacking->color = iconFadedBackingColor; | |||
| 10159 | } | |||
| 10160 | } | |||
| 10161 | if ( promptInfo.promptType == ACTION_PROMPT_OFFHAND && skillForPrompt == PRO_SHIELD | |||
| 10162 | && sneakingSeparateFromBlock ) | |||
| 10163 | { | |||
| 10164 | if ( !stats[player.playernum]->defending ) | |||
| 10165 | { | |||
| 10166 | //glyph->disabled = true; | |||
| 10167 | img->color = iconFadedColor; | |||
| 10168 | //imgBacking->color = iconFadedBackingColor; | |||
| 10169 | } | |||
| 10170 | } | |||
| 10171 | } | |||
| 10172 | } | |||
| 10173 | ++index; | |||
| 10174 | } | |||
| 10175 | } | |||
| 10176 | ||||
| 10177 | static Frame* createMinimap(int player); | |||
| 10178 | ||||
| 10179 | void createGameTimerFrame(const int player) | |||
| 10180 | { | |||
| 10181 | auto& hud_t = players[player]->hud; | |||
| 10182 | hud_t.gameTimerFrame = hud_t.hudFrame->addFrame("timer"); | |||
| 10183 | hud_t.gameTimerFrame->setHollow(true); | |||
| 10184 | hud_t.gameTimerFrame->setDisabled(true); | |||
| 10185 | hud_t.gameTimerFrame->setSize(SDL_Rect{ 0, 0, 142, 24 }); | |||
| 10186 | ||||
| 10187 | auto txt = hud_t.gameTimerFrame->addField("timer txt", 64); | |||
| 10188 | txt->setText("00:00:00"); | |||
| 10189 | txt->setSize(SDL_Rect{ 0, 0, hud_t.gameTimerFrame->getSize().w, hud_t.gameTimerFrame->getSize().h }); | |||
| 10190 | txt->setFont("fonts/pixel_maz_multiline.ttf#16#2"); | |||
| 10191 | txt->setVJustify(Field::justify_t::TOP); | |||
| 10192 | txt->setHJustify(Field::justify_t::LEFT); | |||
| 10193 | txt->setColor(makeColor(255, 255, 255, 255)); | |||
| 10194 | ||||
| 10195 | auto seed = hud_t.gameTimerFrame->addField("seed txt", 64); | |||
| 10196 | seed->setText(""); | |||
| 10197 | seed->setSize(SDL_Rect{ 0, 0, hud_t.gameTimerFrame->getSize().w, hud_t.gameTimerFrame->getSize().h }); | |||
| 10198 | seed->setFont("fonts/pixel_maz_multiline.ttf#16#2"); | |||
| 10199 | seed->setVJustify(Field::justify_t::TOP); | |||
| 10200 | seed->setHJustify(Field::justify_t::RIGHT); | |||
| 10201 | seed->setColor(makeColor(255, 255, 255, 255)); | |||
| 10202 | seed->setDisabled(true); | |||
| 10203 | } | |||
| 10204 | ||||
| 10205 | void createMapPromptFrame(const int player) | |||
| 10206 | { | |||
| 10207 | auto& hud_t = players[player]->hud; | |||
| 10208 | hud_t.mapPromptFrame = hud_t.hudFrame->addFrame("map prompts"); | |||
| 10209 | hud_t.mapPromptFrame->setHollow(true); | |||
| 10210 | hud_t.mapPromptFrame->setDisabled(true); | |||
| 10211 | hud_t.mapPromptFrame->setSize(SDL_Rect{ 0, 0, 142, 24 }); | |||
| 10212 | ||||
| 10213 | auto promptBg = hud_t.mapPromptFrame->addImage(SDL_Rect{ 0, 0, 280, 40 }, | |||
| 10214 | 0xFFFFFFFF, "*#images/ui/MapAndLog/HUD_MapPromptBase_00.png", "prompt bg"); | |||
| 10215 | ||||
| 10216 | auto imgPromptFrame = hud_t.mapPromptFrame->addFrame("img prompt frame"); | |||
| 10217 | imgPromptFrame->setHollow(true); | |||
| 10218 | ||||
| 10219 | auto scaleImg = imgPromptFrame->addImage(SDL_Rect{ 0, 0, 24, 24 }, | |||
| 10220 | 0xFFFFFFFF, "*#images/ui/MapAndLog/HUD_Map_Zoom_00.png", "scale img"); | |||
| 10221 | auto scalePrompt = imgPromptFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 10222 | 0xFFFFFFFF, "*#images/system/white.png", "scale prompt"); | |||
| 10223 | ||||
| 10224 | auto expandImg = imgPromptFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 10225 | 0xFFFFFFFF, "*#images/ui/MapAndLog/HUD_Map_Scale_00.png", "expand img"); | |||
| 10226 | auto expandPrompt = imgPromptFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 10227 | 0xFFFFFFFF, "*#images/system/white.png", "expand prompt"); | |||
| 10228 | } | |||
| 10229 | ||||
| 10230 | static void checkControllerState(int player) { | |||
| 10231 | auto& controllerFrame = players[player]->hud.controllerFrame; | |||
| 10232 | assert(controllerFrame)(static_cast<void> (0)); | |||
| 10233 | if (multiplayer != SINGLE0) { | |||
| 10234 | player = 0; | |||
| 10235 | } | |||
| 10236 | if (inputs.getPlayerIDAllowedKeyboard() != player) { | |||
| 10237 | auto controller = inputs.getController(player); | |||
| 10238 | if (!controller || (controller && !controller->isActive())) { | |||
| 10239 | if (controllerFrame->isHollow()) { | |||
| 10240 | controllerFrame->setHollow(false); | |||
| 10241 | controllerFrame->setDisabled(false); | |||
| 10242 | MainMenu::controllerDisconnected(player); | |||
| 10243 | } | |||
| 10244 | return; | |||
| 10245 | } | |||
| 10246 | } | |||
| 10247 | controllerFrame->setDisabled(true); | |||
| 10248 | controllerFrame->setHollow(true); | |||
| 10249 | } | |||
| 10250 | ||||
| 10251 | void HUDDrawGameEndHint(const int player, SDL_Rect rect) | |||
| 10252 | { | |||
| 10253 | if ( multiplayer == CLIENT2 || multiplayer == SERVER1 ) | |||
| 10254 | { | |||
| 10255 | bool everyonedead = true; | |||
| 10256 | for ( int i = 0; i < MAXPLAYERS4; ++i ) | |||
| 10257 | { | |||
| 10258 | if ( players[i] ) | |||
| 10259 | { | |||
| 10260 | if ( multiplayer == SERVER1 && (!client_disconnected[i] && players[i]->entity) ) | |||
| 10261 | { | |||
| 10262 | everyonedead = false; | |||
| 10263 | } | |||
| 10264 | else if ( multiplayer == CLIENT2 && players[i]->entity ) | |||
| 10265 | { | |||
| 10266 | everyonedead = false; | |||
| 10267 | } | |||
| 10268 | } | |||
| 10269 | } | |||
| 10270 | ||||
| 10271 | if ( players[player]->bControlEnabled ) | |||
| 10272 | { | |||
| 10273 | players[player]->hud.animDeadPromptDisplay = true; | |||
| 10274 | } | |||
| 10275 | ||||
| 10276 | if ( everyonedead && players[player]->hud.animDeadPromptDisplay ) | |||
| 10277 | { | |||
| 10278 | static ConsoleVariable<float> cvar_anim_dead_prompt_speed("/anim_dead_prompt_speed", 0.003); | |||
| 10279 | players[player]->hud.animDeadPrompt += *cvar_anim_dead_prompt_speed; | |||
| 10280 | if ( players[player]->hud.animDeadPrompt >= 1.0 ) | |||
| 10281 | { | |||
| 10282 | players[player]->hud.animDeadPrompt = 0.0; | |||
| 10283 | } | |||
| 10284 | rect.x += rect.w / 2; | |||
| 10285 | rect.y += 8 - 1; | |||
| 10286 | if ( players[player]->hud.xpFrame && !players[player]->hud.xpFrame->isDisabled() ) | |||
| 10287 | { | |||
| 10288 | rect.y += players[player]->hud.xpFrame->getSize().y; | |||
| 10289 | rect.y += players[player]->hud.xpFrame->getSize().h; | |||
| 10290 | } | |||
| 10291 | if ( auto textGet = Text::get(Language::get(6052), smallfont_outline, makeColorRGB(255, 255, 255), 0) ) | |||
| 10292 | { | |||
| 10293 | Uint8 r, g, b, a; | |||
| 10294 | getColor(hudColors.characterSheetRed, &r, &g, &b, nullptr); | |||
| 10295 | real_t opacity = 0.5 + .4 * (1.0 * cos(players[player]->hud.animDeadPrompt * 2 * PI3.14159265358979323846) + 1.0); | |||
| 10296 | Uint32 color = makeColor(r, g, b, std::max(0.25, std::min(opacity, 1.0)) * 255); | |||
| 10297 | rect.x -= textGet->getWidth() / 2; | |||
| 10298 | textGet->drawColor(SDL_Rect{ 0, 0, 0, 0 }, SDL_Rect{ rect.x, rect.y, 0, 0 }, | |||
| 10299 | SDL_Rect{ 0, 0, Frame::virtualScreenX, Frame::virtualScreenY }, | |||
| 10300 | color); | |||
| 10301 | } | |||
| 10302 | } | |||
| 10303 | else | |||
| 10304 | { | |||
| 10305 | players[player]->hud.animDeadPromptDisplay = false; | |||
| 10306 | players[player]->hud.animDeadPrompt = 0.0; | |||
| 10307 | } | |||
| 10308 | } | |||
| 10309 | else | |||
| 10310 | { | |||
| 10311 | players[player]->hud.animDeadPromptDisplay = false; | |||
| 10312 | players[player]->hud.animDeadPrompt = 0.0; | |||
| 10313 | } | |||
| 10314 | } | |||
| 10315 | ||||
| 10316 | void Player::HUD_t::processHUD() | |||
| 10317 | { | |||
| 10318 | const SDL_Rect hudSize{ | |||
| 10319 | players[player.playernum]->camera_virtualx1(), | |||
| 10320 | players[player.playernum]->camera_virtualy1(), | |||
| 10321 | players[player.playernum]->camera_virtualWidth(), | |||
| 10322 | players[player.playernum]->camera_virtualHeight()}; | |||
| 10323 | ||||
| 10324 | if ( !hudFrame ) | |||
| 10325 | { | |||
| 10326 | char name[32]; | |||
| 10327 | snprintf(name, sizeof(name), "player hud %d", player.playernum); | |||
| 10328 | hudFrame = gameUIFrame[player.playernum]->addFrame(name); | |||
| 10329 | hudFrame->setHollow(true); | |||
| 10330 | hudFrame->setBorder(0); | |||
| 10331 | hudFrame->setOwner(player.playernum); | |||
| 10332 | hudFrame->setDrawCallback([](const Widget& widget, SDL_Rect rect) { | |||
| 10333 | HUDDrawGameEndHint(widget.getOwner(), rect); | |||
| 10334 | }); | |||
| 10335 | } | |||
| 10336 | ||||
| 10337 | if ( !minotaurSharedDisplay && player.playernum == 0 ) | |||
| 10338 | { | |||
| 10339 | minotaurSharedDisplay = gameUIFrame[player.playernum]->addFrame("minotaur shared display"); | |||
| 10340 | minotaurSharedDisplay->setHollow(true); | |||
| 10341 | minotaurSharedDisplay->setOwner(player.playernum); | |||
| 10342 | minotaurSharedDisplay->setDisabled(true); | |||
| 10343 | minotaurSharedDisplay->setInheritParentFrameOpacity(false); | |||
| 10344 | auto img = minotaurSharedDisplay->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "*images/ui/HUD/HUD_Minotaur_00.png", | |||
| 10345 | "mino img"); | |||
| 10346 | if ( auto imgGet = Image::get(img->path.c_str()) ) | |||
| 10347 | { | |||
| 10348 | img->pos.w = imgGet->getWidth(); | |||
| 10349 | img->pos.h = imgGet->getHeight(); | |||
| 10350 | } | |||
| 10351 | minotaurSharedDisplay->setSize(SDL_Rect{ 0, 0, img->pos.w, img->pos.h }); | |||
| 10352 | } | |||
| 10353 | ||||
| 10354 | if ( !minotaurDisplay ) | |||
| 10355 | { | |||
| 10356 | minotaurDisplay = hudFrame->addFrame("minotaur display"); | |||
| 10357 | minotaurDisplay->setHollow(true); | |||
| 10358 | minotaurDisplay->setOwner(player.playernum); | |||
| 10359 | minotaurDisplay->setDisabled(true); | |||
| 10360 | minotaurDisplay->setInheritParentFrameOpacity(false); | |||
| 10361 | auto img = minotaurDisplay->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "*images/ui/HUD/HUD_Minotaur_00.png", | |||
| 10362 | "mino img"); | |||
| 10363 | if ( auto imgGet = Image::get(img->path.c_str()) ) | |||
| 10364 | { | |||
| 10365 | img->pos.w = imgGet->getWidth(); | |||
| 10366 | img->pos.h = imgGet->getHeight(); | |||
| 10367 | } | |||
| 10368 | minotaurDisplay->setSize(SDL_Rect{ 0, 0, img->pos.w, img->pos.h }); | |||
| 10369 | } | |||
| 10370 | ||||
| 10371 | if ( !controllerFrame ) | |||
| 10372 | { | |||
| 10373 | controllerFrame = gameUIFrame[player.playernum]->addFrame("reconnect_controller"); | |||
| 10374 | controllerFrame->setColor(0); | |||
| 10375 | controllerFrame->setOwner(player.playernum); | |||
| 10376 | controllerFrame->setBorder(0); | |||
| 10377 | controllerFrame->setDisabled(true); | |||
| 10378 | controllerFrame->setHollow(true); | |||
| 10379 | controllerFrame->setTickCallback([](Widget& widget){ | |||
| 10380 | const int player = widget.getOwner(); | |||
| 10381 | const bool disabled = ticks % TICKS_PER_SECOND50 >= TICKS_PER_SECOND50 / 2; | |||
| 10382 | const SDL_Rect hudSize{ | |||
| 10383 | players[player]->camera_virtualx1(), | |||
| 10384 | players[player]->camera_virtualy1(), | |||
| 10385 | players[player]->camera_virtualWidth(), | |||
| 10386 | players[player]->camera_virtualHeight()}; | |||
| 10387 | auto frame = static_cast<Frame*>(&widget); assert(frame)(static_cast<void> (0)); | |||
| 10388 | auto image = frame->findImage("controller"); assert(image)(static_cast<void> (0)); | |||
| 10389 | image->pos.x = (hudSize.w - image->pos.w) / 2; | |||
| 10390 | image->pos.y = (hudSize.h - image->pos.h) / 2; | |||
| 10391 | image->disabled = disabled; | |||
| 10392 | auto field = frame->findField("label"); assert(field)(static_cast<void> (0)); | |||
| 10393 | field->setSize(image->pos); | |||
| 10394 | field->setInvisible(disabled); | |||
| 10395 | }); | |||
| 10396 | ||||
| 10397 | auto dimmer = controllerFrame->addImage( | |||
| 10398 | SDL_Rect{0, 0, hudSize.w, hudSize.h}, | |||
| 10399 | makeColor(0, 0, 0, 191), | |||
| 10400 | "#*images/system/white.png", | |||
| 10401 | "dimmer"); | |||
| 10402 | ||||
| 10403 | const char* path = Input::getControllerGlyph(player.playernum); | |||
| 10404 | auto image = Image::get(path); | |||
| 10405 | const int w = image->getWidth(); | |||
| 10406 | const int h = image->getHeight(); | |||
| 10407 | const int x = (hudSize.w - w) / 2; | |||
| 10408 | const int y = (hudSize.h - h) / 2; | |||
| 10409 | auto controller = controllerFrame->addImage( | |||
| 10410 | SDL_Rect{x, y, w, h}, | |||
| 10411 | 0xffffffff, path, | |||
| 10412 | "controller"); | |||
| 10413 | ||||
| 10414 | char fmt[16]; | |||
| 10415 | snprintf(fmt, sizeof(fmt), Language::get(5477), player.playernum + 1); | |||
| 10416 | ||||
| 10417 | auto field = controllerFrame->addField("label", 16); | |||
| 10418 | field->setSize(SDL_Rect{x, y, w, h}); | |||
| 10419 | field->setJustify(Field::justify_t::CENTER); | |||
| 10420 | field->setText(fmt); | |||
| 10421 | field->setFont(bigfont_outline); | |||
| 10422 | field->setColor(playerColor(player.playernum, colorblind_lobby, false)); | |||
| 10423 | } | |||
| 10424 | ||||
| 10425 | controllerFrame->setSize(hudSize); | |||
| 10426 | hudFrame->setSize(hudSize); | |||
| 10427 | ||||
| 10428 | if ( gamePaused || nohud || !players[player.playernum]->isLocalPlayer() ) | |||
| 10429 | { | |||
| 10430 | // hide | |||
| 10431 | hudFrame->setDisabled(true); | |||
| 10432 | controllerFrame->setDisabled(true); | |||
| 10433 | } | |||
| 10434 | else | |||
| 10435 | { | |||
| 10436 | hudFrame->setDisabled(false); | |||
| 10437 | if ( !controllerFrame->isHollow() ) | |||
| 10438 | { | |||
| 10439 | controllerFrame->setDisabled(false); | |||
| 10440 | } | |||
| 10441 | } | |||
| 10442 | ||||
| 10443 | static ConsoleVariable<bool> cvar_disable_controller_reconnect("/disable_controller_reconnect", false); | |||
| 10444 | if ( !*cvar_disable_controller_reconnect ) | |||
| 10445 | { | |||
| 10446 | if ( MainMenu::isPlayerSignedIn(player.playernum) && players[player.playernum]->isLocalPlayer() ) | |||
| 10447 | { | |||
| 10448 | checkControllerState(player.playernum); | |||
| 10449 | } | |||
| 10450 | } | |||
| 10451 | static ConsoleVariable<int> cvar_ui_above_hotbar_y("/ui_above_hotbar_y", 56); | |||
| 10452 | offsetHUDAboveHotbarHeight = 0; | |||
| 10453 | if ( player.bUseCompactGUIWidth() ) | |||
| 10454 | { | |||
| 10455 | #ifndef NINTENDO | |||
| 10456 | if ( inputs.hasController(player.playernum) ) | |||
| 10457 | { | |||
| 10458 | if ( !playerSettings[multiplayer ? 0 : player.playernum].gamepad_facehotbar || *cvar_hotbar_compact_disable ) | |||
| 10459 | { | |||
| 10460 | offsetHUDAboveHotbarHeight = *cvar_ui_above_hotbar_y; | |||
| 10461 | } | |||
| 10462 | } | |||
| 10463 | else if ( inputs.bPlayerUsingKeyboardControl(player.playernum) ) | |||
| 10464 | { | |||
| 10465 | offsetHUDAboveHotbarHeight = *cvar_ui_above_hotbar_y; | |||
| 10466 | } | |||
| 10467 | #else | |||
| 10468 | if ( !playerSettings[multiplayer ? 0 : player.playernum].gamepad_facehotbar || *cvar_hotbar_compact_disable ) | |||
| 10469 | { | |||
| 10470 | offsetHUDAboveHotbarHeight = *cvar_ui_above_hotbar_y; | |||
| 10471 | } | |||
| 10472 | #endif // NINTENDO | |||
| 10473 | } | |||
| 10474 | ||||
| 10475 | if ( !gamePaused && (player.entity || player.ghost.isActive()) && player.shootmode) | |||
| 10476 | { | |||
| 10477 | inputs.getVirtualMouse(player.playernum)->draw_cursor = false; | |||
| 10478 | } | |||
| 10479 | ||||
| 10480 | if ( !this->minimapFrame ) | |||
| 10481 | { | |||
| 10482 | this->minimapFrame = createMinimap(player.playernum); | |||
| 10483 | } | |||
| 10484 | if ( !mapPromptFrame ) | |||
| 10485 | { | |||
| 10486 | createMapPromptFrame(player.playernum); | |||
| 10487 | } | |||
| 10488 | if ( !gameTimerFrame ) | |||
| 10489 | { | |||
| 10490 | createGameTimerFrame(player.playernum); | |||
| 10491 | } | |||
| 10492 | if ( !xpFrame ) | |||
| 10493 | { | |||
| 10494 | createXPBar(player.playernum); | |||
| 10495 | } | |||
| 10496 | if ( !hpFrame ) | |||
| 10497 | { | |||
| 10498 | createHPMPBars(player.playernum); | |||
| 10499 | } | |||
| 10500 | if ( !calloutPromptFrame ) | |||
| 10501 | { | |||
| 10502 | createCalloutPromptFrame(player.playernum); | |||
| 10503 | } | |||
| 10504 | if ( !enemyBarFrame ) | |||
| 10505 | { | |||
| 10506 | createEnemyBar(player.playernum, enemyBarFrame); | |||
| 10507 | } | |||
| 10508 | if ( !enemyBarFrameHUD ) | |||
| 10509 | { | |||
| 10510 | createEnemyBar(player.playernum, enemyBarFrameHUD); | |||
| 10511 | } | |||
| 10512 | if ( !StatusEffectQueue[player.playernum].statusEffectFrame ) | |||
| 10513 | { | |||
| 10514 | createStatusEffectQueue(player.playernum); | |||
| 10515 | } | |||
| 10516 | if ( !allyFollowerTitleFrame ) | |||
| 10517 | { | |||
| 10518 | createAllyFollowerTitleFrame(player.playernum); | |||
| 10519 | } | |||
| 10520 | if ( !allyFollowerFrame ) | |||
| 10521 | { | |||
| 10522 | createAllyFollowerFrame(player.playernum); | |||
| 10523 | } | |||
| 10524 | if ( !allyPlayerFrame ) | |||
| 10525 | { | |||
| 10526 | createAllyPlayerFrame(player.playernum); | |||
| 10527 | } | |||
| 10528 | ||||
| 10529 | updateMinimapPrompts(); | |||
| 10530 | updateGameTimer(); | |||
| 10531 | updateAllyFollowerFrame(player.playernum); | |||
| 10532 | updateAllyPlayerFrame(player.playernum); | |||
| 10533 | updateXPBar(); | |||
| 10534 | updateHPBar(); | |||
| 10535 | updateMPBar(); | |||
| 10536 | updateCalloutPromptFrame(player.playernum); | |||
| 10537 | updateActionPrompts(); | |||
| 10538 | updateUINavigation(); | |||
| 10539 | enemyHPDamageBarHandler[player.playernum].cullExpiredHPBars(); | |||
| 10540 | enemyBarFrame->setDisabled(true); | |||
| 10541 | enemyBarFrameHUD->setDisabled(true); | |||
| 10542 | for ( auto& HPBar : enemyHPDamageBarHandler[player.playernum].HPBars ) | |||
| 10543 | { | |||
| 10544 | updateEnemyBar2(enemyBarFrame, &HPBar.second); | |||
| 10545 | } | |||
| 10546 | updateStatusEffectQueue(player.playernum); | |||
| 10547 | } | |||
| 10548 | ||||
| 10549 | void Player::MessageZone_t::createChatbox() | |||
| 10550 | { | |||
| 10551 | char name[32]; | |||
| 10552 | snprintf(name, sizeof(name), "player chat %d", player.playernum); | |||
| 10553 | if ( !gameUIFrame[player.playernum]->findFrame(name) ) | |||
| 10554 | { | |||
| 10555 | Frame* chatMainFrame = gameUIFrame[player.playernum]->addFrame(name); | |||
| 10556 | chatMainFrame->setHollow(true); | |||
| 10557 | chatMainFrame->setBorder(0); | |||
| 10558 | chatMainFrame->setOwner(player.playernum); | |||
| 10559 | chatMainFrame->setSize(SDL_Rect{ players[player.playernum]->camera_virtualx1(), | |||
| 10560 | players[player.playernum]->camera_virtualy1(), | |||
| 10561 | players[player.playernum]->camera_virtualWidth(), | |||
| 10562 | players[player.playernum]->camera_virtualHeight() }); | |||
| 10563 | chatFrame = chatMainFrame; | |||
| 10564 | Frame* messages = chatMainFrame->addFrame("message box"); | |||
| 10565 | messages->setHollow(true); | |||
| 10566 | messages->setInheritParentFrameOpacity(false); | |||
| 10567 | ||||
| 10568 | static const char* bigfont = "fonts/pixelmix.ttf#16#2"; | |||
| 10569 | SDL_Rect entryPos{ 0, 0, messages->getSize().w, messages->getSize().h }; | |||
| 10570 | for ( int i = 0; i < MESSAGE_MAX_ENTRIES; ++i ) | |||
| 10571 | { | |||
| 10572 | char msgName[32]; | |||
| 10573 | snprintf(msgName, sizeof(msgName), "message %d", i); | |||
| 10574 | auto entry = messages->addField(msgName, ADD_MESSAGE_BUFFER_LENGTH); | |||
| 10575 | entry->setFont(bigfont); | |||
| 10576 | entry->setSize(entryPos); | |||
| 10577 | entry->setDisabled(true); | |||
| 10578 | entry->setVJustify(Field::justify_t::TOP); | |||
| 10579 | } | |||
| 10580 | } | |||
| 10581 | } | |||
| 10582 | ||||
| 10583 | static ConsoleVariable<int> cvar_log_lineheight_offset("/log_lineheight_offset", -6); | |||
| 10584 | static ConsoleVariable<int> cvar_log_lineheight_min("/log_lineheight_minimum", 24); | |||
| 10585 | static ConsoleVariable<int> cvar_log_multiline_pady("/log_multiline_pady", -4); | |||
| 10586 | const char* Player::MessageZone_t::bigfont = "fonts/pixelmix.ttf#16#2"; | |||
| 10587 | const char* Player::MessageZone_t::smallfont = "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 10588 | static ConsoleVariable<int> cvar_message_fade_min("/message_fade_min", 25); | |||
| 10589 | void Player::MessageZone_t::processChatbox() | |||
| 10590 | { | |||
| 10591 | if (!chatFrame) { | |||
| 10592 | createChatbox(); | |||
| 10593 | } | |||
| 10594 | ||||
| 10595 | chatFrame->setSize(SDL_Rect{ player.camera_virtualx1(), | |||
| 10596 | player.camera_virtualy1(), | |||
| 10597 | player.camera_virtualWidth(), | |||
| 10598 | player.camera_virtualHeight() }); | |||
| 10599 | ||||
| 10600 | int playercount = 0; | |||
| 10601 | for (int c = 0; c < MAXPLAYERS4; ++c) { | |||
| 10602 | if (!client_disconnected[c] && players[c]->isLocalPlayer()) { | |||
| 10603 | ++playercount; | |||
| 10604 | } | |||
| 10605 | } | |||
| 10606 | ||||
| 10607 | Frame* messageBoxFrame = chatFrame->findFrame("message box"); | |||
| 10608 | messageBoxFrame->setDisabled(gamePaused || (!player.shootmode && playercount > 2)); | |||
| 10609 | if (messageBoxFrame->isDisabled()) { | |||
| 10610 | return; | |||
| 10611 | } | |||
| 10612 | ||||
| 10613 | static const char* bigfont = "fonts/pixelmix.ttf#16#2"; | |||
| 10614 | static const char* smallfont = "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 10615 | static ConsoleVariable<bool> cvar_smallmessages("/smallmessages", false); | |||
| 10616 | //static ConsoleVariable<bool> cvar_top_aligned("/topmessages", false); | |||
| 10617 | //static ConsoleVariable<std::string> alignment("/alignmessages", ""); | |||
| 10618 | static ConsoleVariable<std::string> cvar_setalignment("/alignmessages", ""); | |||
| 10619 | static ConsoleVariable<int> cvar_messages_left_y("/messages_left_y", 200); | |||
| 10620 | useBigFont = !player.bUseCompactGUIHeight() && !player.bUseCompactGUIWidth();// || (playercount == 2 && !*MainMenu::vertical_splitscreen); | |||
| 10621 | if ( *cvar_smallmessages ) | |||
| 10622 | { | |||
| 10623 | useBigFont = false; | |||
| 10624 | } | |||
| 10625 | ||||
| 10626 | if ( *cvar_setalignment == "left" ) | |||
| 10627 | { | |||
| 10628 | messageAlignment = ALIGN_LEFT_BOTTOM; | |||
| 10629 | } | |||
| 10630 | else if ( *cvar_setalignment == "top" ) | |||
| 10631 | { | |||
| 10632 | messageAlignment = ALIGN_LEFT_TOP; | |||
| 10633 | } | |||
| 10634 | else if ( *cvar_setalignment == "center" ) | |||
| 10635 | { | |||
| 10636 | messageAlignment = ALIGN_CENTER_BOTTOM; | |||
| 10637 | } | |||
| 10638 | ||||
| 10639 | actualAlignment = ALIGN_LEFT_BOTTOM; | |||
| 10640 | if ( player.bUseCompactGUIHeight() && player.bUseCompactGUIWidth() ) | |||
| 10641 | { | |||
| 10642 | actualAlignment = ALIGN_LEFT_TOP; | |||
| 10643 | } | |||
| 10644 | else if ( messageAlignment == ALIGN_CENTER_BOTTOM ) | |||
| 10645 | { | |||
| 10646 | if ( !player.bUseCompactGUIHeight() ) | |||
| 10647 | { | |||
| 10648 | // allowed in tall or singleplayer | |||
| 10649 | actualAlignment = messageAlignment; | |||
| 10650 | } | |||
| 10651 | else | |||
| 10652 | { | |||
| 10653 | actualAlignment = ALIGN_LEFT_TOP; // else default to top-left in wide 2-player | |||
| 10654 | if ( !player.shootmode | |||
| 10655 | && (player.gui_mode == GUI_MODE_INVENTORY || player.gui_mode == GUI_MODE_SHOP) ) | |||
| 10656 | { | |||
| 10657 | actualAlignment = ALIGN_LEFT_BOTTOM; | |||
| 10658 | } | |||
| 10659 | } | |||
| 10660 | } | |||
| 10661 | else if ( messageAlignment == ALIGN_LEFT_BOTTOM ) | |||
| 10662 | { | |||
| 10663 | actualAlignment = messageAlignment; // ok in all configs | |||
| 10664 | } | |||
| 10665 | else if ( messageAlignment == ALIGN_LEFT_TOP ) | |||
| 10666 | { | |||
| 10667 | actualAlignment = messageAlignment; | |||
| 10668 | if ( playercount <= 2 && !player.shootmode | |||
| 10669 | && (player.gui_mode == GUI_MODE_INVENTORY || player.gui_mode == GUI_MODE_SHOP) ) | |||
| 10670 | { | |||
| 10671 | actualAlignment = ALIGN_LEFT_BOTTOM; | |||
| 10672 | } | |||
| 10673 | } | |||
| 10674 | ||||
| 10675 | switch ( actualAlignment ) | |||
| 10676 | { | |||
| 10677 | case ALIGN_CENTER_BOTTOM: | |||
| 10678 | bottomAlignedMessages = true; | |||
| 10679 | break; | |||
| 10680 | case ALIGN_LEFT_BOTTOM: | |||
| 10681 | bottomAlignedMessages = true; | |||
| 10682 | break; | |||
| 10683 | case ALIGN_LEFT_TOP: | |||
| 10684 | bottomAlignedMessages = false; | |||
| 10685 | break; | |||
| 10686 | default: | |||
| 10687 | break; | |||
| 10688 | } | |||
| 10689 | ||||
| 10690 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 10691 | if ( player.bUseCompactGUIWidth() && actualAlignment == ALIGN_LEFT_TOP && | |||
| 10692 | ((player.hud.levelupFrame && !player.hud.levelupFrame->isDisabled()) | |||
| 10693 | || (player.hud.skillupFrame && !player.hud.skillupFrame->isDisabled())) ) | |||
| 10694 | { | |||
| 10695 | animFade -= fpsScale * std::max(.1, (animFade)) / (2.5); | |||
| 10696 | animFade = std::max(0.0, animFade); | |||
| 10697 | } | |||
| 10698 | else | |||
| 10699 | { | |||
| 10700 | animFade += fpsScale * std::max(.1, (1.0 - animFade)) / (5.0); | |||
| 10701 | animFade = std::min(1.0, animFade); | |||
| 10702 | } | |||
| 10703 | ||||
| 10704 | messageBoxFrame->setOpacity(*cvar_message_fade_min + (100.0 - *cvar_message_fade_min) * animFade); | |||
| 10705 | ||||
| 10706 | bool pushPaddingX = !player.shootmode | |||
| 10707 | && actualAlignment != ALIGN_CENTER_BOTTOM | |||
| 10708 | && (player.gui_mode == GUI_MODE_INVENTORY || player.gui_mode == GUI_MODE_SHOP) | |||
| 10709 | && ((playercount == 1 | |||
| 10710 | && player.inventoryUI.getSizeY() > player.inventoryUI.DEFAULT_INVENTORY_SIZEY) || | |||
| 10711 | (playercount == 2 && !*MainMenu::vertical_splitscreen)); | |||
| 10712 | ||||
| 10713 | auto& messageLayoutSetting = messageZoneSettings.getLayout(player.playernum, actualAlignment); | |||
| 10714 | MESSAGE_MAX_ENTRIES = messageLayoutSetting.maxMessages; | |||
| 10715 | ||||
| 10716 | const int leftAlignedPaddingX = pushPaddingX ? 240 : 8; | |||
| 10717 | int leftAlignedBottomY = *cvar_messages_left_y; | |||
| 10718 | leftAlignedBottomY += messageLayoutSetting.offsetY; | |||
| 10719 | if ( player.bUseCompactGUIHeight() ) | |||
| 10720 | { | |||
| 10721 | if ( StatusEffectQueue[player.playernum].statusEffectFrame ) | |||
| 10722 | { | |||
| 10723 | const int hungerIconSize = 64; | |||
| 10724 | if ( actualAlignment == ALIGN_LEFT_BOTTOM ) | |||
| 10725 | { | |||
| 10726 | leftAlignedBottomY = players[player.playernum]->camera_virtualy2() | |||
| 10727 | - (StatusEffectQueue[player.playernum].statusEffectFrame->getSize().y | |||
| 10728 | + StatusEffectQueue[player.playernum].statusEffectFrame->getSize().h | |||
| 10729 | - hungerIconSize - 8); | |||
| 10730 | } | |||
| 10731 | } | |||
| 10732 | } | |||
| 10733 | const int topAlignedPaddingX = 8; | |||
| 10734 | int topAlignedPaddingY = 8; | |||
| 10735 | if ( player.hud.allyPlayerFrame && actualAlignment == ALIGN_LEFT_TOP && !splitscreen ) | |||
| 10736 | { | |||
| 10737 | SDL_Rect allyPlayerPos = player.hud.allyPlayerFrame->getSize(); | |||
| 10738 | if ( !player.hud.allyPlayerFrame->isDisabled() && allyPlayerPos.h > 0 ) | |||
| 10739 | { | |||
| 10740 | topAlignedPaddingY = 4 + allyPlayerPos.y + allyPlayerPos.h; | |||
| 10741 | } | |||
| 10742 | } | |||
| 10743 | if ( player.hud.xpFrame && actualAlignment == ALIGN_LEFT_TOP ) | |||
| 10744 | { | |||
| 10745 | SDL_Rect xpFramePos = player.hud.xpFrame->getSize(); | |||
| 10746 | topAlignedPaddingY = std::max(topAlignedPaddingY, 4 + std::max(xpFramePos.y, 0) + xpFramePos.h); | |||
| 10747 | if ( !(player.bUseCompactGUIHeight() && player.bUseCompactGUIWidth()) ) | |||
| 10748 | { | |||
| 10749 | topAlignedPaddingY += 4; | |||
| 10750 | } | |||
| 10751 | } | |||
| 10752 | SDL_Rect messageboxTopAlignedPos{ | |||
| 10753 | topAlignedPaddingX, | |||
| 10754 | topAlignedPaddingY, | |||
| 10755 | player.camera_virtualWidth() - topAlignedPaddingX * 2, | |||
| 10756 | player.camera_virtualHeight() - topAlignedPaddingY }; | |||
| 10757 | SDL_Rect messageboxLeftAlignedPos{ | |||
| 10758 | leftAlignedPaddingX, | |||
| 10759 | 0, | |||
| 10760 | player.camera_virtualWidth() - leftAlignedPaddingX * 2, | |||
| 10761 | player.camera_virtualHeight() - leftAlignedBottomY }; | |||
| 10762 | ||||
| 10763 | ||||
| 10764 | SDL_Rect messageBoxSize = bottomAlignedMessages ? | |||
| 10765 | messageboxLeftAlignedPos : messageboxTopAlignedPos; | |||
| 10766 | ||||
| 10767 | for ( int i = 0; i < MESSAGE_MAX_ENTRIES; ++i ) | |||
| 10768 | { | |||
| 10769 | char msgName[32]; | |||
| 10770 | snprintf(msgName, sizeof(msgName), "message %d", i); | |||
| 10771 | if ( auto entry = messageBoxFrame->findField(msgName) ) | |||
| 10772 | { | |||
| 10773 | entry->setDisabled(true); | |||
| 10774 | ||||
| 10775 | // set alignment | |||
| 10776 | if ( actualAlignment == ALIGN_CENTER_BOTTOM ) { | |||
| 10777 | entry->setHJustify(Field::justify_t::CENTER); | |||
| 10778 | } else { | |||
| 10779 | entry->setHJustify(Field::justify_t::LEFT); | |||
| 10780 | } | |||
| 10781 | } | |||
| 10782 | } | |||
| 10783 | ||||
| 10784 | const bool messageDrawDescending = (actualAlignment == ALIGN_LEFT_TOP); | |||
| 10785 | const int entryPaddingY = playercount > 2 ? 0 : 4; | |||
| 10786 | ||||
| 10787 | int currentY = messageDrawDescending ? | |||
| 10788 | 0 : messageBoxSize.h; | |||
| 10789 | ||||
| 10790 | int index = 0; | |||
| 10791 | int currentline = 0; | |||
| 10792 | ||||
| 10793 | auto it = notification_messages.begin(); | |||
| 10794 | auto end = notification_messages.end(); | |||
| 10795 | auto rit = notification_messages.rbegin(); | |||
| 10796 | auto rend = notification_messages.rend(); | |||
| 10797 | int textLinePadding = useBigFont ? 0 : -4; | |||
| 10798 | for ( ; messageDrawDescending ? rit != rend : it != end; ++it, ++rit ) | |||
| 10799 | { | |||
| 10800 | Message* current = messageDrawDescending ? *rit : *it; | |||
| 10801 | if ( currentline >= MESSAGE_MAX_ENTRIES) | |||
| 10802 | { | |||
| 10803 | break; | |||
| 10804 | } | |||
| 10805 | ||||
| 10806 | Uint32 color = (current->text->color & 0x00ffffff) | ((Uint32)current->alpha << 24); | |||
| 10807 | ||||
| 10808 | char msgName[32]; | |||
| 10809 | snprintf(msgName, sizeof(msgName), "message %d", index); | |||
| 10810 | if ( auto entry = messageBoxFrame->findField(msgName) ) | |||
| 10811 | { | |||
| 10812 | entry->setDisabled(false); | |||
| 10813 | entry->setColor(color); | |||
| 10814 | ||||
| 10815 | std::string data = messageSanitizePercentSign(current->text->data, nullptr); | |||
| 10816 | char str[ADD_MESSAGE_BUFFER_LENGTH]; | |||
| 10817 | snprintf(str, sizeof(str), data.c_str()); | |||
| 10818 | ||||
| 10819 | entry->setText(str); | |||
| 10820 | entry->setFont(useBigFont ? bigfont : smallfont); | |||
| 10821 | entry->setPaddingPerLine(useBigFont ? 0 : *cvar_log_multiline_pady); | |||
| 10822 | Font* fontGet = Font::get(entry->getFont()); | |||
| 10823 | Text* textGet = entry->getTextObject(); | |||
| 10824 | ||||
| 10825 | int w = textGet->getWidth(); | |||
| 10826 | int h = textGet->getHeight() * (current->text->lines + textLinePadding); | |||
| 10827 | int textHeight = h; | |||
| 10828 | if ( !useBigFont ) | |||
| 10829 | { | |||
| 10830 | int h2 = (int)(std::max(*cvar_log_lineheight_min + 2, | |||
| 10831 | ((int)textGet->getHeight() + textLinePadding) * textGet->getNumTextLines() + textLinePadding)); | |||
| 10832 | textHeight = h2; | |||
| 10833 | h = textHeight + *cvar_log_lineheight_offset; | |||
| 10834 | } | |||
| 10835 | ||||
| 10836 | if (!messageDrawDescending) { | |||
| 10837 | currentY -= h; | |||
| 10838 | currentY -= entryPaddingY; | |||
| 10839 | } | |||
| 10840 | ||||
| 10841 | SDL_Rect pos = entry->getSize(); | |||
| 10842 | pos.x = 0; | |||
| 10843 | pos.y = currentY; | |||
| 10844 | pos.w = messageBoxFrame->getSize().w; | |||
| 10845 | pos.h = textHeight; | |||
| 10846 | entry->setSize(pos); | |||
| 10847 | ||||
| 10848 | if (messageDrawDescending) { | |||
| 10849 | currentY += h; | |||
| 10850 | currentY += entryPaddingY; | |||
| 10851 | } | |||
| 10852 | } | |||
| 10853 | ++index; | |||
| 10854 | currentline += current->text->lines; | |||
| 10855 | } | |||
| 10856 | ||||
| 10857 | messageBoxFrame->setSize(messageBoxSize); | |||
| 10858 | } | |||
| 10859 | ||||
| 10860 | ConsoleVariable<bool> shareMinimap("/shareminimap", true); | |||
| 10861 | ConsoleVariable<bool> cvar_minimap_prompt_vertical("/minimap_prompt_vertical", false); | |||
| 10862 | Frame* minimapFrame = nullptr; // shared minimap | |||
| 10863 | SDL_Rect Player::Minimap_t::sharedMinimapPos{ 0, 0, 0, 0 }; | |||
| 10864 | int Player::Minimap_t::fullSize = 200; | |||
| 10865 | int Player::Minimap_t::compactSize = 200; | |||
| 10866 | int Player::Minimap_t::compact2pVerticalSize = 200; | |||
| 10867 | real_t Player::Minimap_t::fullBigScale = 100.0; | |||
| 10868 | real_t Player::Minimap_t::compactBigScale = 100.0; | |||
| 10869 | real_t Player::Minimap_t::compact2pVerticalBigScale = 100.0; | |||
| 10870 | bool Player::Minimap_t::bUpdateMainMenuSettingScale = false; | |||
| 10871 | real_t Player::Minimap_t::mainMenuSettingScale = 1.0; | |||
| 10872 | ||||
| 10873 | void doSharedMinimap() { | |||
| 10874 | if (!minimapFrame) { | |||
| 10875 | minimapFrame = gui->addFrame("shared_minimap"); | |||
| 10876 | minimapFrame->setColor(0); | |||
| 10877 | minimapFrame->setHollow(true); | |||
| 10878 | minimapFrame->setInvisible(true); | |||
| 10879 | minimapFrame->setDrawCallback([](const Widget& widget, SDL_Rect rect){ | |||
| 10880 | drawMinimap(widget.getOwner(), rect, true); | |||
| 10881 | }); | |||
| 10882 | minimapFrame->setTickCallback([](Widget& widget){ | |||
| 10883 | int playercount = 0; | |||
| 10884 | for (int c = 0; c < MAXPLAYERS4; ++c) { | |||
| 10885 | if (!client_disconnected[c] && players[c]->isLocalPlayer()) { | |||
| 10886 | ++playercount; | |||
| 10887 | } | |||
| 10888 | } | |||
| 10889 | if (gamePaused || intro || MainMenu::isCutsceneActive() || playercount < 3 || !*shareMinimap) { | |||
| 10890 | minimapFrame->setInvisible(true); | |||
| 10891 | } else { | |||
| 10892 | minimapFrame->setInvisible(false); | |||
| 10893 | } | |||
| 10894 | if (playercount == 3) { | |||
| 10895 | const int size = std::min(Frame::virtualScreenX / 2, Frame::virtualScreenY / 2); | |||
| 10896 | minimapFrame->setSize(SDL_Rect{ | |||
| 10897 | (Frame::virtualScreenX + ((Frame::virtualScreenX / 2) - size)) / 2, | |||
| 10898 | (Frame::virtualScreenY + ((Frame::virtualScreenY / 2) - size)) / 2, | |||
| 10899 | size, size}); | |||
| 10900 | } else if (playercount == 4) { | |||
| 10901 | constexpr int size = 128; | |||
| 10902 | minimapFrame->setSize(SDL_Rect{ | |||
| 10903 | (Frame::virtualScreenX - size) / 2, | |||
| 10904 | Frame::virtualScreenY / 2, | |||
| 10905 | size, size}); | |||
| 10906 | } | |||
| 10907 | Player::Minimap_t::sharedMinimapPos = static_cast<Frame*>(&widget)->getSize(); | |||
| 10908 | }); | |||
| 10909 | } | |||
| 10910 | minimapFrame->setOwner(clientnum); | |||
| 10911 | } | |||
| 10912 | ||||
| 10913 | static Frame* createMinimap(int player) { | |||
| 10914 | std::string name = "minimap"; | |||
| 10915 | name.append(std::to_string(player)); | |||
| 10916 | auto& minimap = players[player]->minimap; | |||
| 10917 | minimap.real_scale = minimapScale; | |||
| 10918 | minimap.scale = minimapScale; | |||
| 10919 | Frame* parent = players[player]->hud.hudFrame; | |||
| 10920 | Frame* window = parent->addFrame(name.c_str()); | |||
| 10921 | window->setSize(SDL_Rect{0, 0, 0, 0}); | |||
| 10922 | window->setColor(0); | |||
| 10923 | window->setOwner(player); | |||
| 10924 | window->setDrawCallback([](const Widget& widget, SDL_Rect rect){ | |||
| 10925 | drawMinimap(widget.getOwner(), rect, false); | |||
| 10926 | }); | |||
| 10927 | ||||
| 10928 | window->setTickCallback([](Widget& widget){ | |||
| 10929 | int playercount = 0; | |||
| 10930 | for (int c = 0; c < MAXPLAYERS4; ++c) { | |||
| 10931 | if (!client_disconnected[c] && players[c]->isLocalPlayer()) { | |||
| 10932 | ++playercount; | |||
| 10933 | } | |||
| 10934 | } | |||
| 10935 | ||||
| 10936 | widget.setInvisible(*shareMinimap && playercount > 2); | |||
| 10937 | auto player = widget.getOwner(); | |||
| 10938 | auto& input = Input::inputs[player]; | |||
| 10939 | auto& minimap = players[player]->minimap; | |||
| 10940 | bool reducedSize = playercount > 2 /*|| (playercount == 2 && *MainMenu::vertical_splitscreen)*/; | |||
| 10941 | ||||
| 10942 | minimap.bExpandPromptEnabled = true; | |||
| 10943 | minimap.bScalePromptEnabled = false; | |||
| 10944 | if ( !players[player]->shootmode ) | |||
| 10945 | { | |||
| 10946 | minimap.bExpandPromptEnabled = false; | |||
| 10947 | minimap.bScalePromptEnabled = false; | |||
| 10948 | } | |||
| 10949 | else if ( players[player]->worldUI.isEnabled() | |||
| 10950 | && players[player]->worldUI.bTooltipInView | |||
| 10951 | && players[player]->worldUI.tooltipsInRange.size() > 1 ) | |||
| 10952 | { | |||
| 10953 | const std::string scaleBinding = input.binding("Minimap Scale"); | |||
| 10954 | const std::string expandBinding = input.binding("Toggle Minimap"); | |||
| 10955 | const std::string cycleNextBinding = input.binding("Interact Tooltip Next"); | |||
| 10956 | const std::string cyclePrevBinding = input.binding("Interact Tooltip Prev"); | |||
| 10957 | if ( scaleBinding == cycleNextBinding | |||
| 10958 | || scaleBinding == cyclePrevBinding ) | |||
| 10959 | { | |||
| 10960 | minimap.bScalePromptEnabled = false; | |||
| 10961 | } | |||
| 10962 | if ( expandBinding == cycleNextBinding | |||
| 10963 | || expandBinding == cyclePrevBinding ) | |||
| 10964 | { | |||
| 10965 | minimap.bExpandPromptEnabled = false; | |||
| 10966 | } | |||
| 10967 | } | |||
| 10968 | ||||
| 10969 | if ( !gamePaused && players[player]->bControlEnabled && minimap.bScalePromptEnabled | |||
| 10970 | && !players[player]->usingCommand() && players[player]->shootmode && input.consumeBinaryToggle("Minimap Scale")) { | |||
| 10971 | if (minimap.scale > 75.0) { | |||
| 10972 | minimap.real_scale = 75.0; | |||
| 10973 | } | |||
| 10974 | else if (minimap.scale > 50.0) { | |||
| 10975 | minimap.real_scale = 50.0; | |||
| 10976 | } | |||
| 10977 | else if (minimap.scale > 25.0) { | |||
| 10978 | minimap.real_scale = 25.0; | |||
| 10979 | } | |||
| 10980 | else { | |||
| 10981 | minimap.real_scale = reducedSize ? 75.0 : 100.0; | |||
| 10982 | } | |||
| 10983 | } | |||
| 10984 | ||||
| 10985 | auto& scale_ang = minimap.scale_ang; | |||
| 10986 | auto& scale = minimap.scale; | |||
| 10987 | minimap.animating = true; | |||
| 10988 | if (minimap.big) { | |||
| 10989 | if (scale_ang < PI3.14159265358979323846 / 2.0) { | |||
| 10990 | scale_ang += ((PI3.14159265358979323846 / 144.0) * 2.0) * getFPSScale(144.0); | |||
| 10991 | if (scale_ang > PI3.14159265358979323846 / 2.0) { | |||
| 10992 | scale_ang = PI3.14159265358979323846 / 2.0; | |||
| 10993 | } | |||
| 10994 | } | |||
| 10995 | if ( scale_ang >= PI3.14159265358979323846 / 2.0 ) | |||
| 10996 | { | |||
| 10997 | minimap.animating = false; | |||
| 10998 | } | |||
| 10999 | } else { | |||
| 11000 | if (scale_ang > 0.0) { | |||
| 11001 | scale_ang -= ((PI3.14159265358979323846 / 144.0) * 2.0) * getFPSScale(144.0); | |||
| 11002 | if (scale_ang < 0.0) { | |||
| 11003 | scale_ang = 0.0; | |||
| 11004 | } | |||
| 11005 | } | |||
| 11006 | if ( scale_ang <= 0.0 ) | |||
| 11007 | { | |||
| 11008 | minimap.animating = false; | |||
| 11009 | } | |||
| 11010 | } | |||
| 11011 | ||||
| 11012 | real_t factor0 = 1.0 - sin(scale_ang); | |||
| 11013 | real_t factor1 = sin(scale_ang); | |||
| 11014 | //real_t scale_small = std::min(reducedSize ? 25.0 : 50.0, minimap.real_scale); | |||
| 11015 | //real_t scale_big = std::min(reducedSize ? 75.0 : 100.0, minimap.real_scale); | |||
| 11016 | real_t scale_small = 50.0; | |||
| 11017 | real_t scale_big = Player::Minimap_t::fullBigScale; | |||
| 11018 | int maxSize = Player::Minimap_t::fullSize; | |||
| 11019 | static ConsoleVariable<int> cvar_minimap_compact_offset_y("/minimap_compact_offset_y", 44); | |||
| 11020 | int mapBigOffsetY = 0; | |||
| 11021 | if ( players[player]->bUseCompactGUIHeight() ) // 2p wide | |||
| 11022 | { | |||
| 11023 | maxSize = Player::Minimap_t::compactSize; | |||
| 11024 | scale_big = Player::Minimap_t::compactBigScale; | |||
| 11025 | mapBigOffsetY = *cvar_minimap_compact_offset_y; | |||
| 11026 | } | |||
| 11027 | else if ( !players[player]->bUseCompactGUIHeight() && players[player]->bUseCompactGUIWidth() ) // 2p vertical | |||
| 11028 | { | |||
| 11029 | maxSize = Player::Minimap_t::compact2pVerticalSize; | |||
| 11030 | scale_big = Player::Minimap_t::compact2pVerticalBigScale; | |||
| 11031 | } | |||
| 11032 | ||||
| 11033 | { | |||
| 11034 | real_t scale = factor0 * scale_small; | |||
| 11035 | players[player]->minimap.minimapPos.w = (int)((scale / 100.0) * maxSize); | |||
| 11036 | players[player]->minimap.minimapPos.h = (int)((scale / 100.0) * maxSize); | |||
| 11037 | } | |||
| 11038 | ||||
| 11039 | scale = factor0 * scale_small + factor1 * scale_big; | |||
| 11040 | ||||
| 11041 | Frame* parent = players[player]->hud.hudFrame; | |||
| 11042 | ||||
| 11043 | int mapHeightOffset = 0; | |||
| 11044 | if ( players[player]->hud.mapPromptFrame && !players[player]->hud.mapPromptFrame->isDisabled() ) | |||
| 11045 | { | |||
| 11046 | mapHeightOffset = players[player]->hud.mapPromptFrame->getSize().h; | |||
| 11047 | } | |||
| 11048 | else if ( players[player]->hud.gameTimerFrame && !players[player]->hud.gameTimerFrame->isDisabled() | |||
| 11049 | // ignore if ui raised above hotbar and vertical split layout | |||
| 11050 | && (!(players[player]->hud.offsetHUDAboveHotbarHeight > 0 && splitscreen && !players[player]->bUseCompactGUIHeight() && players[player]->bUseCompactGUIWidth())) ) | |||
| 11051 | { | |||
| 11052 | mapHeightOffset = players[player]->hud.gameTimerFrame->getSize().h; | |||
| 11053 | } | |||
| 11054 | mapHeightOffset += players[player]->hud.offsetHUDAboveHotbarHeight; | |||
| 11055 | ||||
| 11056 | const int scaledSize = (int)((scale / 100.0) * maxSize); | |||
| 11057 | int x = factor0 * (parent->getSize().w - scaledSize) + | |||
| 11058 | factor1 * (parent->getSize().w - scaledSize) / 2; | |||
| 11059 | int y = factor0 * (parent->getSize().h - scaledSize - mapHeightOffset) + | |||
| 11060 | factor1 * (parent->getSize().h - scaledSize - mapBigOffsetY) / 2; | |||
| 11061 | ||||
| 11062 | auto frame = static_cast<Frame*>(&widget); | |||
| 11063 | frame->setSize(SDL_Rect{x, y, (int)(scaledSize), (int)(scaledSize)}); | |||
| 11064 | players[player]->minimap.minimapPos.x = x; | |||
| 11065 | players[player]->minimap.minimapPos.y = y; | |||
| 11066 | if ( frame->isInvisible() ) | |||
| 11067 | { | |||
| 11068 | frame->setHollow(true); | |||
| 11069 | } | |||
| 11070 | else | |||
| 11071 | { | |||
| 11072 | frame->setHollow(true); | |||
| 11073 | } | |||
| 11074 | }); | |||
| 11075 | ||||
| 11076 | return window; | |||
| 11077 | } | |||
| 11078 | ||||
| 11079 | void openMinimap(int player) { | |||
| 11080 | Frame* minimap = players[player]->hud.minimapFrame; | |||
| 11081 | if (minimap) { | |||
| 11082 | players[player]->minimap.big = (players[player]->minimap.big==false); | |||
| 11083 | } | |||
| 11084 | } | |||
| 11085 | ||||
| 11086 | void Player::MessageZone_t::processLogFrame() | |||
| 11087 | { | |||
| 11088 | if ( !logParentFrame ) | |||
| 11089 | { | |||
| 11090 | Frame* f = gameUIFrame[player.playernum]->addFrame("log parent frame"); | |||
| 11091 | f->setHollow(true); | |||
| 11092 | f->setDisabled(true); | |||
| 11093 | f->setBorder(0); | |||
| 11094 | f->setOwner(player.playernum); | |||
| 11095 | logParentFrame = f; | |||
| 11096 | } | |||
| 11097 | ||||
| 11098 | if ( logWindow ) | |||
| 11099 | { | |||
| 11100 | logParentFrame->setDisabled(false); | |||
| 11101 | } | |||
| 11102 | else | |||
| 11103 | { | |||
| 11104 | if ( player.hud.hudFrame ) | |||
| 11105 | { | |||
| 11106 | logParentFrame->setDisabled(player.hud.hudFrame->isDisabled()); | |||
| 11107 | } | |||
| 11108 | else | |||
| 11109 | { | |||
| 11110 | logParentFrame->setDisabled(true); | |||
| 11111 | } | |||
| 11112 | } | |||
| 11113 | ||||
| 11114 | if ( !logParentFrame->isDisabled() ) | |||
| 11115 | { | |||
| 11116 | logParentFrame->setSize(SDL_Rect{ players[player.playernum]->camera_virtualx1(), | |||
| 11117 | players[player.playernum]->camera_virtualy1(), | |||
| 11118 | players[player.playernum]->camera_virtualWidth(), | |||
| 11119 | players[player.playernum]->camera_virtualHeight() }); | |||
| 11120 | } | |||
| 11121 | } | |||
| 11122 | void Player::Minimap_t::processMapFrame() | |||
| 11123 | { | |||
| 11124 | if ( !mapParentFrame ) | |||
| 11125 | { | |||
| 11126 | Frame* f = gameUIFrame[player.playernum]->addFrame("map parent frame"); | |||
| 11127 | f->setHollow(true); | |||
| 11128 | f->setDisabled(true); | |||
| 11129 | f->setBorder(0); | |||
| 11130 | f->setOwner(player.playernum); | |||
| 11131 | mapParentFrame = f; | |||
| 11132 | } | |||
| 11133 | ||||
| 11134 | if ( mapWindow ) | |||
| 11135 | { | |||
| 11136 | mapParentFrame->setDisabled(false); | |||
| 11137 | } | |||
| 11138 | else | |||
| 11139 | { | |||
| 11140 | if ( player.hud.hudFrame ) | |||
| 11141 | { | |||
| 11142 | mapParentFrame->setDisabled(player.hud.hudFrame->isDisabled()); | |||
| 11143 | } | |||
| 11144 | else | |||
| 11145 | { | |||
| 11146 | mapParentFrame->setDisabled(true); | |||
| 11147 | } | |||
| 11148 | } | |||
| 11149 | ||||
| 11150 | if ( !mapParentFrame->isDisabled() ) | |||
| 11151 | { | |||
| 11152 | mapParentFrame->setSize(SDL_Rect{ players[player.playernum]->camera_virtualx1(), | |||
| 11153 | players[player.playernum]->camera_virtualy1(), | |||
| 11154 | players[player.playernum]->camera_virtualWidth(), | |||
| 11155 | players[player.playernum]->camera_virtualHeight() }); | |||
| 11156 | } | |||
| 11157 | } | |||
| 11158 | ||||
| 11159 | void openMapWindow(int player) { | |||
| 11160 | if ( !players[player]->minimap.mapParentFrame ) | |||
| 11161 | { | |||
| 11162 | return; | |||
| 11163 | } | |||
| 11164 | auto& frame = players[player]->minimap.mapWindow; | |||
| 11165 | if (frame) { | |||
| 11166 | frame->removeSelf(); | |||
| 11167 | frame = nullptr; | |||
| 11168 | if ( players[player]->gui_mode == GUI_MODE_NONE ) { | |||
| 11169 | players[player]->shootmode = true; | |||
| 11170 | } | |||
| 11171 | else | |||
| 11172 | { | |||
| 11173 | players[player]->GUI.returnToPreviousActiveModule(); | |||
| 11174 | } | |||
| 11175 | Player::soundCancel(); | |||
| 11176 | return; | |||
| 11177 | } | |||
| 11178 | ||||
| 11179 | players[player]->GUI.previousModule = players[player]->GUI.activeModule; | |||
| 11180 | bool bOldShootmode = players[player]->shootmode; | |||
| 11181 | if ( players[player]->shootmode ) | |||
| 11182 | { | |||
| 11183 | players[player]->openStatusScreen(GUI_MODE_NONE, | |||
| 11184 | INVENTORY_MODE_ITEM, Player::GUI_t::MODULE_MAP); | |||
| 11185 | } | |||
| 11186 | else | |||
| 11187 | { | |||
| 11188 | players[player]->openStatusScreen(GUI_MODE_INVENTORY, | |||
| 11189 | players[player]->inventory_mode, Player::GUI_t::MODULE_MAP); // Reset the GUI to the inventory. | |||
| 11190 | } | |||
| 11191 | ||||
| 11192 | Player::soundActivate(); | |||
| 11193 | ||||
| 11194 | auto& otherWindow = players[player]->messageZone.logWindow; | |||
| 11195 | if (otherWindow) { | |||
| 11196 | otherWindow->removeSelf(); | |||
| 11197 | otherWindow = nullptr; | |||
| 11198 | } | |||
| 11199 | Frame* parent = players[player]->minimap.mapParentFrame; | |||
| 11200 | const SDL_Rect size = parent->getSize(); | |||
| 11201 | int _w = std::max(Frame::virtualScreenX / 2, size.w - 432); | |||
| 11202 | int _h = std::max(Frame::virtualScreenY / 2, size.h - 256); | |||
| 11203 | int yoffset = 32; | |||
| 11204 | const bool bCompact = players[player]->bUseCompactGUIHeight() || players[player]->bUseCompactGUIWidth(); | |||
| 11205 | if ( bCompact ) | |||
| 11206 | { | |||
| 11207 | if ( players[player]->bUseCompactGUIHeight() && players[player]->bUseCompactGUIWidth() ) | |||
| 11208 | { | |||
| 11209 | static ConsoleVariable<int> cvar_map_splitscreen_w("/map_splitscreen_wborder", 64); | |||
| 11210 | static ConsoleVariable<int> cvar_map_splitscreen_h("/map_splitscreen_hborder", 16); | |||
| 11211 | static ConsoleVariable<int> cvar_map_splitscreen_offset_y("/map_splitscreen_offset_y", 0); | |||
| 11212 | _w = size.w - *cvar_map_splitscreen_w; | |||
| 11213 | _h = size.h - *cvar_map_splitscreen_h; | |||
| 11214 | yoffset = *cvar_map_splitscreen_offset_y; | |||
| 11215 | } | |||
| 11216 | else if ( players[player]->bUseCompactGUIHeight() ) | |||
| 11217 | { | |||
| 11218 | static ConsoleVariable<int> cvar_map_splitscreen_2p_wide_w("/map_splitscreen_2p_wide_wborder", 64); | |||
| 11219 | static ConsoleVariable<int> cvar_map_splitscreen_2p_wide_h("/map_splitscreen_2p_wide_hborder", 8); | |||
| 11220 | static ConsoleVariable<int> cvar_map_splitscreen_2p_wide_offset_y("/map_splitscreen_2p_wide_offset_y", 0); | |||
| 11221 | _w = size.w - *cvar_map_splitscreen_2p_wide_w; | |||
| 11222 | _h = size.h - *cvar_map_splitscreen_2p_wide_h; | |||
| 11223 | yoffset = *cvar_map_splitscreen_2p_wide_offset_y; | |||
| 11224 | } | |||
| 11225 | else if ( players[player]->bUseCompactGUIWidth() ) | |||
| 11226 | { | |||
| 11227 | static ConsoleVariable<int> cvar_map_splitscreen_2p_tall_w("/map_splitscreen_2p_tall_wborder", 64); | |||
| 11228 | static ConsoleVariable<int> cvar_map_splitscreen_2p_tall_h("/map_splitscreen_2p_tall_hborder", 64); | |||
| 11229 | static ConsoleVariable<int> cvar_map_splitscreen_2p_wide_offset_y("/map_splitscreen_2p_tall_offset_y", 0); | |||
| 11230 | if ( *MainMenu::clipped_splitscreen ) | |||
| 11231 | { | |||
| 11232 | *cvar_map_splitscreen_2p_tall_h = 156; | |||
| 11233 | *cvar_map_splitscreen_2p_wide_offset_y = 2; | |||
| 11234 | } | |||
| 11235 | else | |||
| 11236 | { | |||
| 11237 | *cvar_map_splitscreen_2p_tall_h = 256; | |||
| 11238 | *cvar_map_splitscreen_2p_wide_offset_y = 32; | |||
| 11239 | } | |||
| 11240 | _w = size.w - *cvar_map_splitscreen_2p_tall_w; | |||
| 11241 | _h = size.h - *cvar_map_splitscreen_2p_tall_h; | |||
| 11242 | yoffset = *cvar_map_splitscreen_2p_wide_offset_y; | |||
| 11243 | } | |||
| 11244 | } | |||
| 11245 | int w = std::min(_w, _h); | |||
| 11246 | int h = std::min(_w, _h); | |||
| 11247 | frame = parent->addFrame("minimap_window"); | |||
| 11248 | frame->setOwner(player); | |||
| 11249 | frame->setSize(SDL_Rect{(size.w - w) / 2, (size.h - h) / 2 - yoffset, w, h}); | |||
| 11250 | frame->setBorderColor(makeColor(51, 33, 26, 255)); | |||
| 11251 | frame->setColor(0); | |||
| 11252 | //frame->setBorder(2); | |||
| 11253 | frame->setBorder(0); | |||
| 11254 | frame->setColor(makeColor(mapBgColor->x, mapBgColor->y, mapBgColor->z, mapBgColor->w)); | |||
| 11255 | frame->setTickCallback([](Widget& widget){ | |||
| 11256 | const int player = widget.getOwner(); | |||
| 11257 | auto frame = static_cast<Frame*>(&widget); | |||
| 11258 | if (players[player]->shootmode) { | |||
| 11259 | players[player]->minimap.mapWindow = nullptr; | |||
| 11260 | frame->removeSelf(); | |||
| 11261 | } | |||
| 11262 | }); | |||
| 11263 | ||||
| 11264 | // frame images | |||
| 11265 | { | |||
| 11266 | frame->addImage( | |||
| 11267 | SDL_Rect{0, 0, 16, 32}, | |||
| 11268 | 0xffffffff, | |||
| 11269 | "*#images/ui/MapAndLog/Hover_TL00.png", | |||
| 11270 | "TL"); | |||
| 11271 | frame->addImage( | |||
| 11272 | SDL_Rect{16, 0, w - 32, 32}, | |||
| 11273 | 0xffffffff, | |||
| 11274 | "*#images/ui/MapAndLog/Hover_T00.png", | |||
| 11275 | "T"); | |||
| 11276 | frame->addImage( | |||
| 11277 | SDL_Rect{w - 16, 0, 16, 32}, | |||
| 11278 | 0xffffffff, | |||
| 11279 | "*#images/ui/MapAndLog/Hover_TR00.png", | |||
| 11280 | "TR"); | |||
| 11281 | auto L = frame->addImage( | |||
| 11282 | SDL_Rect{0, 32, 4, h - 48}, | |||
| 11283 | 0xffffffff, | |||
| 11284 | "*#images/ui/MapAndLog/Hover_L00.png", | |||
| 11285 | "L"); | |||
| 11286 | L->ontop = true; | |||
| 11287 | auto R = frame->addImage( | |||
| 11288 | SDL_Rect{w - 4, 32, 4, h - 48}, | |||
| 11289 | 0xffffffff, | |||
| 11290 | "*#images/ui/MapAndLog/Hover_R00.png", | |||
| 11291 | "R"); | |||
| 11292 | R->ontop = true; | |||
| 11293 | auto BL = frame->addImage( | |||
| 11294 | SDL_Rect{0, h - 16, 16, 16}, | |||
| 11295 | 0xffffffff, | |||
| 11296 | "*#images/ui/MapAndLog/Hover_BL00.png", | |||
| 11297 | "BL"); | |||
| 11298 | BL->ontop = true; | |||
| 11299 | auto B = frame->addImage( | |||
| 11300 | SDL_Rect{16, h - 4, w - 32, 4}, | |||
| 11301 | 0xffffffff, | |||
| 11302 | "*#images/ui/MapAndLog/Hover_B00.png", | |||
| 11303 | "B"); | |||
| 11304 | B->ontop = true; | |||
| 11305 | auto BR = frame->addImage( | |||
| 11306 | SDL_Rect{w - 16, h - 16, 16, 16}, | |||
| 11307 | 0xffffffff, | |||
| 11308 | "*#images/ui/MapAndLog/Hover_BR00.png", | |||
| 11309 | "BR"); | |||
| 11310 | BR->ontop = true; | |||
| 11311 | } | |||
| 11312 | ||||
| 11313 | auto container = frame->addFrame("container"); | |||
| 11314 | container->setSize(SDL_Rect{0, 32, w, h - 32}); | |||
| 11315 | container->setBorderColor(makeColor(51, 33, 26, 255)); | |||
| 11316 | //container->setBorder(2); | |||
| 11317 | container->setBorder(0); | |||
| 11318 | container->setColor(0); | |||
| 11319 | ||||
| 11320 | const int map_size = std::min(w - 32, h - 64); | |||
| 11321 | auto minimap = container->addFrame("minimap"); | |||
| 11322 | minimap->setSize(SDL_Rect{(w - map_size) / 2, (h - 32 - map_size) / 2, map_size, map_size}); | |||
| 11323 | minimap->setColor(0); | |||
| 11324 | minimap->setBorder(0); | |||
| 11325 | ||||
| 11326 | struct Position { | |||
| 11327 | real_t x; | |||
| 11328 | real_t y; | |||
| 11329 | }; | |||
| 11330 | static Position minimap_cursor[MAXPLAYERS4]; | |||
| 11331 | minimap_cursor[player].x = map_size / 2; | |||
| 11332 | minimap_cursor[player].y = map_size / 2; | |||
| 11333 | ||||
| 11334 | if ( !bOldShootmode && players[player]->GUI.previousModule == Player::GUI_t::MODULE_CHARACTERSHEET ) | |||
| 11335 | { | |||
| 11336 | if ( !inputs.getVirtualMouse(player)->draw_cursor ) | |||
| 11337 | { | |||
| 11338 | Input::inputs[player].consumeBinary("MinimapPing"); // clicked from button | |||
| 11339 | } | |||
| 11340 | } | |||
| 11341 | ||||
| 11342 | minimap->setDrawCallback([](const Widget& widget, SDL_Rect rect){ | |||
| 11343 | int player = widget.getOwner(); | |||
| 11344 | if ( ::minimapFrame && !::minimapFrame->isInvisible() ) | |||
| 11345 | { | |||
| 11346 | drawMinimap(0, rect, true); // use the same texture | |||
| 11347 | } | |||
| 11348 | else | |||
| 11349 | { | |||
| 11350 | drawMinimap(player, rect, false); | |||
| 11351 | } | |||
| 11352 | if (!inputs.getVirtualMouse(player)->draw_cursor) { | |||
| 11353 | auto& cursor = minimap_cursor[player]; | |||
| 11354 | auto image = Image::get("*#images/ui/MapAndLog/cursor.png"); | |||
| 11355 | SDL_Rect pos; | |||
| 11356 | pos.x = cursor.x - image->getWidth() / 2 + rect.x; | |||
| 11357 | pos.y = cursor.y - image->getHeight() / 2 + rect.y; | |||
| 11358 | pos.w = image->getWidth(); | |||
| 11359 | pos.h = image->getHeight(); | |||
| 11360 | image->drawColor(nullptr, pos, SDL_Rect{0, 0, Frame::virtualScreenX, Frame::virtualScreenY}, 0xffffffff); | |||
| 11361 | } | |||
| 11362 | else | |||
| 11363 | { | |||
| 11364 | auto frame = ((Frame*)(widget.getParent()))->getParent(); | |||
| 11365 | if ( Button* button = frame->findButton("close") ) | |||
| 11366 | { | |||
| 11367 | if ( button->isHighlighted() ) | |||
| 11368 | { | |||
| 11369 | players[player]->GUI.setHoveringOverModuleButton(Player::GUI_t::MODULE_MAP); | |||
| 11370 | if ( players[player]->GUI.activeModule != Player::GUI_t::MODULE_MAP ) | |||
| 11371 | { | |||
| 11372 | players[player]->GUI.activateModule(Player::GUI_t::MODULE_MAP); | |||
| 11373 | } | |||
| 11374 | SDL_Rect pos = button->getAbsoluteSize(); | |||
| 11375 | // make sure to adjust absolute size to camera viewport | |||
| 11376 | pos.x -= players[player]->camera_virtualx1(); | |||
| 11377 | pos.y -= players[player]->camera_virtualy1(); | |||
| 11378 | players[player]->hud.setCursorDisabled(false); | |||
| 11379 | players[player]->hud.updateCursorAnimation(pos.x - 1, pos.y - 1, pos.w, pos.h, inputs.getVirtualMouse(player)->draw_cursor); | |||
| 11380 | } | |||
| 11381 | } | |||
| 11382 | } | |||
| 11383 | }); | |||
| 11384 | ||||
| 11385 | minimap->setTickCallback([](Widget& widget){ | |||
| 11386 | int player = widget.getOwner(); | |||
| 11387 | auto& input = Input::inputs[player]; | |||
| 11388 | auto minimap = static_cast<Frame*>(&widget); | |||
| 11389 | ||||
| 11390 | auto frame = ((Frame*)(widget.getParent()))->getParent(); | |||
| 11391 | if ( Frame::image_t* closeGlyph = frame->findImage("close glyph") ) | |||
| 11392 | { | |||
| 11393 | closeGlyph->disabled = true; | |||
| 11394 | if ( inputs.hasController(player) && !inputs.getVirtualMouse(player)->draw_cursor ) | |||
| 11395 | { | |||
| 11396 | Button* closeBtn = frame->findButton("close"); | |||
| 11397 | SDL_Rect closeBtnPos = closeBtn->getSize(); | |||
| 11398 | closeBtn->setSize(closeBtnPos); | |||
| 11399 | ||||
| 11400 | closeGlyph->path = Input::inputs[player].getGlyphPathForBinding("MinimapClose"); | |||
| 11401 | if ( auto imgGet = Image::get(closeGlyph->path.c_str()) ) | |||
| 11402 | { | |||
| 11403 | closeGlyph->pos.w = imgGet->getWidth(); | |||
| 11404 | closeGlyph->pos.h = imgGet->getHeight(); | |||
| 11405 | closeGlyph->disabled = false; | |||
| 11406 | } | |||
| 11407 | closeGlyph->pos.x = closeBtn->getSize().x + closeBtn->getSize().w / 2 - closeGlyph->pos.w / 2; | |||
| 11408 | if ( closeGlyph->pos.x % 2 == 1 ) | |||
| 11409 | { | |||
| 11410 | ++closeGlyph->pos.x; | |||
| 11411 | } | |||
| 11412 | closeGlyph->pos.y = closeBtn->getSize().y + closeBtn->getSize().h - 4; | |||
| 11413 | } | |||
| 11414 | } | |||
| 11415 | ||||
| 11416 | static ConsoleVariable<float> speed("/minimap_cursor_speed", 4.f); | |||
| 11417 | ||||
| 11418 | // gamepad moves cursor with right stick | |||
| 11419 | auto& cursor = minimap_cursor[player]; | |||
| 11420 | const real_t fpsScale = getFPSScale(60.0); // ported from 60Hz | |||
| 11421 | float leftright = (input.analog("MinimapRight") - input.analog("MinimapLeft")); | |||
| 11422 | float updown = (input.analog("MinimapDown") - input.analog("MinimapUp")); | |||
| 11423 | cursor.x += (leftright) * (*speed * fpsScale); | |||
| 11424 | cursor.y += (updown) * (*speed * fpsScale); | |||
| 11425 | cursor.x = std::min(std::max((real_t)0, cursor.x), (real_t)minimap->getSize().w); | |||
| 11426 | cursor.y = std::min(std::max((real_t)0, cursor.y), (real_t)minimap->getSize().h); | |||
| 11427 | input.consumeBindingsSharedWithBinding("MinimapRight"); | |||
| 11428 | input.consumeBindingsSharedWithBinding("MinimapLeft"); | |||
| 11429 | input.consumeBindingsSharedWithBinding("MinimapDown"); | |||
| 11430 | input.consumeBindingsSharedWithBinding("MinimapUp"); | |||
| 11431 | if (input.consumeBinaryToggle("MinimapClose")) { | |||
| 11432 | input.consumeBindingsSharedWithBinding("MinimapClose"); | |||
| 11433 | if (players[player]->minimap.mapWindow) { | |||
| 11434 | players[player]->minimap.mapWindow->removeSelf(); | |||
| 11435 | players[player]->minimap.mapWindow = nullptr; | |||
| 11436 | if (players[player]->gui_mode == GUI_MODE_NONE) { | |||
| 11437 | players[player]->shootmode = true; | |||
| 11438 | } | |||
| 11439 | else | |||
| 11440 | { | |||
| 11441 | players[player]->GUI.returnToPreviousActiveModule(); | |||
| 11442 | } | |||
| 11443 | Player::soundCancel(); | |||
| 11444 | } | |||
| 11445 | } | |||
| 11446 | ||||
| 11447 | static ConsoleVariable<bool> minimapGimpEnabled("/minimap_gimp_enabled", true); | |||
| 11448 | ||||
| 11449 | // minimap pings | |||
| 11450 | if (minimapPingGimpTimer[player] <= 0 || !*minimapGimpEnabled) { | |||
| 11451 | if (input.consumeBinaryToggle("MinimapPing")) { | |||
| 11452 | auto mouse_position = inputs.getVirtualMouse(player)->draw_cursor ? | |||
| 11453 | minimap->getRelativeMousePosition(false): | |||
| 11454 | SDL_Rect{(int)cursor.x, (int)cursor.y, minimap->getSize().w, minimap->getSize().h}; | |||
| 11455 | messagePlayer(clientnum, MESSAGE_DEBUG, "[Minimap] Clicked %d %d %d %d", | |||
| 11456 | mouse_position.x, mouse_position.y, mouse_position.w, mouse_position.h); | |||
| 11457 | if (mouse_position.w > 0 && mouse_position.h > 0) { | |||
| 11458 | const int size = std::max((int)map.width, (int)map.height); | |||
| 11459 | const int xdiff = std::max(0, (int)map.height - (int)map.width) / 2; | |||
| 11460 | const int ydiff = std::max(0, (int)map.width - (int)map.height) / 2; | |||
| 11461 | const int x = (mouse_position.x * size) / mouse_position.w - xdiff; | |||
| 11462 | const int y = (mouse_position.y * size) / mouse_position.h - ydiff; | |||
| 11463 | if (x >= 0 && y >= 0 && x < map.width && y < map.height) { | |||
| 11464 | MinimapPing newPing(ticks, player, x, y); | |||
| 11465 | sendMinimapPing(player, newPing.x, newPing.y); | |||
| 11466 | ||||
| 11467 | // can also issue move commands via minimap | |||
| 11468 | FollowerRadialMenu& followerMenu = FollowerMenu[player]; | |||
| 11469 | if ( !followerMenu.menuToggleClick && followerMenu.selectMoveTo ) | |||
| 11470 | { | |||
| 11471 | if ( followerMenu.optionSelected == ALLY_CMD_MOVETO_SELECT ) | |||
| 11472 | { | |||
| 11473 | if (!players[player]->usingCommand() && players[player]->bControlEnabled) { | |||
| 11474 | createParticleFollowerCommand(newPing.x, newPing.y, 0, FOLLOWER_TARGET_PARTICLE, 0); | |||
| 11475 | followerMenu.optionSelected = ALLY_CMD_MOVETO_CONFIRM; | |||
| 11476 | followerMenu.selectMoveTo = false; | |||
| 11477 | followerMenu.moveToX = static_cast<int>(newPing.x); | |||
| 11478 | followerMenu.moveToY = static_cast<int>(newPing.y); | |||
| 11479 | } | |||
| 11480 | } | |||
| 11481 | } | |||
| 11482 | } | |||
| 11483 | } | |||
| 11484 | } | |||
| 11485 | } else { // if (minimapPingGimpTimer[player] <= 0) | |||
| 11486 | --minimapPingGimpTimer[player]; | |||
| 11487 | } | |||
| 11488 | }); | |||
| 11489 | ||||
| 11490 | auto label = frame->addField("label", 64); | |||
| 11491 | label->setSize(SDL_Rect{16, 0, w - 40, 32}); | |||
| 11492 | label->setHJustify(Field::justify_t::LEFT); | |||
| 11493 | label->setVJustify(Field::justify_t::CENTER); | |||
| 11494 | label->setFont(bigfont_outline); | |||
| 11495 | label->setText(Language::get(5966)); | |||
| 11496 | ||||
| 11497 | auto closeGlyph = frame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, | |||
| 11498 | "", "close glyph"); | |||
| 11499 | closeGlyph->disabled = true; | |||
| 11500 | closeGlyph->ontop = true; | |||
| 11501 | ||||
| 11502 | auto close_button = frame->addButton("close"); | |||
| 11503 | close_button->setSize(SDL_Rect{frame->getSize().w - 30, 4, 26, 26}); | |||
| 11504 | close_button->setColor(makeColor(255, 255, 255, 255)); | |||
| 11505 | close_button->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 11506 | close_button->setText("X"); | |||
| 11507 | close_button->setFont(smallfont_outline); | |||
| 11508 | close_button->setHideGlyphs(true); | |||
| 11509 | close_button->setHideKeyboardGlyphs(true); | |||
| 11510 | close_button->setHideSelectors(true); | |||
| 11511 | close_button->setMenuConfirmControlType(0); | |||
| 11512 | close_button->setBackground("*#images/ui/Shop/Button_X_00.png"); | |||
| 11513 | close_button->setBackgroundHighlighted("*#images/ui/Shop/Button_XHigh_00.png"); | |||
| 11514 | close_button->setBackgroundActivated("*#images/ui/Shop/Button_XPress_00.png"); | |||
| 11515 | close_button->setTextHighlightColor(makeColor(201, 162, 100, 255)); | |||
| 11516 | close_button->setCallback([](Button& button){ | |||
| 11517 | const int player = button.getOwner(); | |||
| 11518 | players[player]->minimap.mapWindow = nullptr; | |||
| 11519 | auto parent = static_cast<Frame*>(button.getParent()); | |||
| 11520 | parent->removeSelf(); | |||
| 11521 | if (players[player]->gui_mode == GUI_MODE_NONE) { | |||
| 11522 | players[player]->shootmode = true; | |||
| 11523 | } | |||
| 11524 | Player::soundCancel(); | |||
| 11525 | }); | |||
| 11526 | } | |||
| 11527 | ||||
| 11528 | static ConsoleCommand ccmd_log_clear("/log_clear", "Clears log history", | |||
| 11529 | [](int argc, const char** argv){ | |||
| 11530 | list_FreeAll(&messages); | |||
| 11531 | }); | |||
| 11532 | ||||
| 11533 | void addMessageToLogWindow(int player, string_t* string) { | |||
| 11534 | auto& frame = players[player]->messageZone.logWindow; | |||
| 11535 | if (!frame || !string) { | |||
| 11536 | return; | |||
| 11537 | } | |||
| 11538 | ||||
| 11539 | const int w = frame->getSize().w; | |||
| 11540 | const int h = frame->getSize().h; | |||
| 11541 | ||||
| 11542 | auto subframe = frame->findFrame("subframe"); assert(subframe)(static_cast<void> (0)); | |||
| 11543 | auto subframe_size = subframe->getActualSize(); | |||
| 11544 | int y = subframe_size.h; | |||
| 11545 | if ( y != 4 ) | |||
| 11546 | { | |||
| 11547 | y = subframe_size.h + *cvar_log_lineheight_offset; | |||
| 11548 | } | |||
| 11549 | ||||
| 11550 | static ConsoleVariable<bool> timestamp_messages("/log_timestamp", true); | |||
| 11551 | ||||
| 11552 | char buf[1024]; | |||
| 11553 | const Uint32 time = string->time / TICKS_PER_SECOND50; | |||
| 11554 | const Uint32 hour = time / 3600; | |||
| 11555 | const Uint32 min = (time / 60) % 60; | |||
| 11556 | const Uint32 sec = time % 60; | |||
| 11557 | const int result = *timestamp_messages ? | |||
| 11558 | snprintf(buf, sizeof(buf), "[%.2u:%.2u:%.2u] %s", | |||
| 11559 | hour, min, sec, string->data): | |||
| 11560 | snprintf(buf, sizeof(buf), "%s", string->data); | |||
| 11561 | const int size = std::min(std::max(0, (int)sizeof(buf)), result); | |||
| 11562 | ||||
| 11563 | static ConsoleVariable<std::string> font("/log_font", | |||
| 11564 | "fonts/PixelMaz_monospace.ttf#32#2"); | |||
| 11565 | static ConsoleVariable<std::string> compactfont("/log_font_compact", | |||
| 11566 | "fonts/pixel_maz.ttf#32#2"); | |||
| 11567 | ||||
| 11568 | const bool bCompactWidth = players[player]->bUseCompactGUIWidth(); | |||
| 11569 | auto field = subframe->addField("field", size + 1); | |||
| 11570 | int text_h = 0; | |||
| 11571 | int text_w = 0; | |||
| 11572 | int textHeight = 0; | |||
| 11573 | if ( bCompactWidth ) | |||
| 11574 | { | |||
| 11575 | field->setFont(compactfont->c_str()); | |||
| 11576 | field->setTextColor(string->color); | |||
| 11577 | field->addWordToHighlight(0, makeColorRGB(166, 166, 166)); | |||
| 11578 | field->setText(buf); | |||
| 11579 | field->setPaddingPerLine(*cvar_log_multiline_pady); | |||
| 11580 | if ( auto text = field->getTextObject() ) | |||
| 11581 | { | |||
| 11582 | textHeight = (int)(std::max(*cvar_log_lineheight_min, (int)text->getHeight()) * (int)string->lines + 2); | |||
| 11583 | text_h = textHeight + *cvar_log_lineheight_offset; | |||
| 11584 | text_w = (int)text->getWidth(); | |||
| 11585 | field->setSize(SDL_Rect{ 8, y, text_w, textHeight }); | |||
| 11586 | } | |||
| 11587 | } | |||
| 11588 | else | |||
| 11589 | { | |||
| 11590 | field->setFont(font->c_str()); | |||
| 11591 | field->setTextColor(string->color); | |||
| 11592 | field->addWordToHighlight(0, makeColorRGB(166, 166, 166)); | |||
| 11593 | field->addWordToHighlight(1, makeColorRGB(166, 166, 166)); | |||
| 11594 | field->addWordToHighlight(2, makeColorRGB(166, 166, 166)); | |||
| 11595 | field->addWordToHighlight(3, makeColorRGB(166, 166, 166)); | |||
| 11596 | field->setText(buf); | |||
| 11597 | field->setPaddingPerLine(*cvar_log_multiline_pady); | |||
| 11598 | if ( auto text = field->getTextObject() ) | |||
| 11599 | { | |||
| 11600 | textHeight = (int)(std::max(*cvar_log_lineheight_min, (int)text->getHeight()) * (int)string->lines + 2); | |||
| 11601 | text_h = textHeight + *cvar_log_lineheight_offset; | |||
| 11602 | text_w = (int)text->getWidth(); | |||
| 11603 | field->setSize(SDL_Rect{ 8, y, text_w, textHeight }); | |||
| 11604 | } | |||
| 11605 | } | |||
| 11606 | ||||
| 11607 | //(void)snprintf(buf, sizeof(buf), "[%.2u:%.2u:%.2u]", hour, min, sec); | |||
| 11608 | //field->setTooltip(buf); | |||
| 11609 | ||||
| 11610 | const int new_w = std::max(subframe_size.w, text_w + 8); | |||
| 11611 | ||||
| 11612 | y = std::max(y, 0); | |||
| 11613 | y += textHeight; | |||
| 11614 | if (subframe_size.y >= subframe_size.h - subframe->getSize().h) { | |||
| 11615 | // advance scroll because we're already at bottom | |||
| 11616 | const int limit = new_w > w ? | |||
| 11617 | y - subframe->getSize().h + 16: | |||
| 11618 | y - subframe->getSize().h; | |||
| 11619 | subframe->setActualSize(SDL_Rect{subframe_size.x, | |||
| 11620 | std::max(0, limit), new_w, y}); | |||
| 11621 | } else { | |||
| 11622 | // retain scroll position because we're looking at past history | |||
| 11623 | subframe->setActualSize(SDL_Rect{ | |||
| 11624 | subframe_size.x, subframe_size.y, new_w, y}); | |||
| 11625 | } | |||
| 11626 | } | |||
| 11627 | ||||
| 11628 | void openLogWindow(int player) { | |||
| 11629 | if ( !players[player]->messageZone.logParentFrame ) | |||
| 11630 | { | |||
| 11631 | return; | |||
| 11632 | } | |||
| 11633 | auto& frame = players[player]->messageZone.logWindow; | |||
| 11634 | if (frame) { | |||
| 11635 | frame->removeSelf(); | |||
| 11636 | frame = nullptr; | |||
| 11637 | if ( players[player]->gui_mode == GUI_MODE_NONE ) { | |||
| 11638 | players[player]->shootmode = true; | |||
| 11639 | } | |||
| 11640 | else | |||
| 11641 | { | |||
| 11642 | players[player]->GUI.returnToPreviousActiveModule(); | |||
| 11643 | } | |||
| 11644 | Player::soundCancel(); | |||
| 11645 | return; | |||
| 11646 | } | |||
| 11647 | ||||
| 11648 | players[player]->GUI.previousModule = players[player]->GUI.activeModule; | |||
| 11649 | if ( players[player]->shootmode ) | |||
| 11650 | { | |||
| 11651 | players[player]->openStatusScreen(GUI_MODE_NONE, | |||
| 11652 | INVENTORY_MODE_ITEM, Player::GUI_t::MODULE_LOG); | |||
| 11653 | } | |||
| 11654 | else | |||
| 11655 | { | |||
| 11656 | players[player]->openStatusScreen(GUI_MODE_INVENTORY, | |||
| 11657 | players[player]->inventory_mode, Player::GUI_t::MODULE_LOG); // Reset the GUI to the inventory. | |||
| 11658 | } | |||
| 11659 | ||||
| 11660 | Player::soundActivate(); | |||
| 11661 | ||||
| 11662 | auto& otherWindow = players[player]->minimap.mapWindow; | |||
| 11663 | if (otherWindow) { | |||
| 11664 | otherWindow->removeSelf(); | |||
| 11665 | otherWindow = nullptr; | |||
| 11666 | } | |||
| 11667 | Frame* parent = players[player]->messageZone.logParentFrame; | |||
| 11668 | const SDL_Rect size = parent->getSize(); | |||
| 11669 | int w = std::max(Frame::virtualScreenX / 2, size.w - 432); | |||
| 11670 | int h = std::max(Frame::virtualScreenY / 2, size.h - 256); | |||
| 11671 | static ConsoleVariable<int> cvar_log_splitscreen_w("/log_splitscreen_wborder", 40); | |||
| 11672 | static ConsoleVariable<int> cvar_log_splitscreen_h("/log_splitscreen_hborder", 64); | |||
| 11673 | int yoffset = 32; | |||
| 11674 | if ( (players[player]->bUseCompactGUIHeight() && players[player]->bUseCompactGUIWidth()) | |||
| 11675 | || players[player]->bUseCompactGUIWidth() ) | |||
| 11676 | { | |||
| 11677 | w = size.w - *cvar_log_splitscreen_w; | |||
| 11678 | if ( !(players[player]->bUseCompactGUIWidth() && !players[player]->bUseCompactGUIHeight()) ) // 2p tall splitscreen | |||
| 11679 | { | |||
| 11680 | h = size.h - *cvar_log_splitscreen_h; | |||
| 11681 | } | |||
| 11682 | } | |||
| 11683 | else if ( players[player]->bUseCompactGUIHeight() ) | |||
| 11684 | { | |||
| 11685 | // 2p wide | |||
| 11686 | w = size.w - 432; | |||
| 11687 | h = size.h - 8; | |||
| 11688 | yoffset = 0; | |||
| 11689 | } | |||
| 11690 | ||||
| 11691 | frame = parent->addFrame("log_window"); | |||
| 11692 | frame->setOwner(player); | |||
| 11693 | frame->setSize(SDL_Rect{(size.w - w) / 2, (size.h - h) / 2 - yoffset, w, h}); | |||
| 11694 | frame->setBorderColor(makeColor(51, 33, 26, 255)); | |||
| 11695 | frame->setColor(makeColor(logBgColor->x, logBgColor->y, logBgColor->z, logBgColor->w)); | |||
| 11696 | //frame->setBorder(2); | |||
| 11697 | frame->setBorder(0); | |||
| 11698 | frame->setTickCallback([](Widget& widget){ | |||
| 11699 | const int player = widget.getOwner(); | |||
| 11700 | auto frame = static_cast<Frame*>(&widget); | |||
| 11701 | if (players[player]->shootmode) { | |||
| 11702 | players[player]->messageZone.logWindow = nullptr; | |||
| 11703 | frame->removeSelf(); | |||
| 11704 | } | |||
| 11705 | ||||
| 11706 | const int w = frame->getSize().w; | |||
| 11707 | const int h = frame->getSize().h; | |||
| 11708 | ||||
| 11709 | const bool using_keyboard = Input::inputs[player].getPlayerControlType() == | |||
| 11710 | Input::playerControlType_t::PLAYER_CONTROLLED_BY_KEYBOARD; | |||
| 11711 | ||||
| 11712 | const bool pressed = (ticks % TICKS_PER_SECOND50) >= TICKS_PER_SECOND50 / 2; | |||
| 11713 | ||||
| 11714 | auto help_left = frame->findField("help_left"); assert(help_left)(static_cast<void> (0)); | |||
| 11715 | auto help_center = frame->findField("help_center"); assert(help_center)(static_cast<void> (0)); | |||
| 11716 | auto help_right = frame->findField("help_right"); assert(help_right)(static_cast<void> (0)); | |||
| 11717 | auto help_left_div = frame->findField("help_left_div"); assert(help_left_div)(static_cast<void> (0)); | |||
| 11718 | auto help_center_div = frame->findField("help_center_div"); assert(help_center_div)(static_cast<void> (0)); | |||
| 11719 | auto help_right_div = frame->findField("help_right_div"); assert(help_right_div)(static_cast<void> (0)); | |||
| 11720 | help_left->setDisabled(false); | |||
| 11721 | help_center->setDisabled(false); | |||
| 11722 | help_right->setDisabled(false); | |||
| 11723 | help_left_div->setDisabled(false); | |||
| 11724 | help_center_div->setDisabled(false); | |||
| 11725 | help_right_div->setDisabled(false); | |||
| 11726 | ||||
| 11727 | auto LogHome = frame->findImage("LogHome"); assert(LogHome)(static_cast<void> (0)); | |||
| 11728 | LogHome->disabled = true; | |||
| 11729 | auto LogEnd = frame->findImage("LogEnd"); assert(LogEnd)(static_cast<void> (0)); | |||
| 11730 | LogEnd->disabled = true; | |||
| 11731 | auto LogPageUp = frame->findImage("LogPageUp"); assert(LogPageUp)(static_cast<void> (0)); | |||
| 11732 | LogPageUp->disabled = true; | |||
| 11733 | auto LogPageDown = frame->findImage("LogPageDown"); assert(LogPageDown)(static_cast<void> (0)); | |||
| 11734 | LogPageDown->disabled = true; | |||
| 11735 | auto LogScrollUp = frame->findImage("LogScrollUp"); assert(LogScrollUp)(static_cast<void> (0)); | |||
| 11736 | LogScrollUp->disabled = true; | |||
| 11737 | auto LogScrollDown = frame->findImage("LogScrollDown"); assert(LogScrollDown)(static_cast<void> (0)); | |||
| 11738 | LogScrollDown->disabled = true; | |||
| 11739 | ||||
| 11740 | const bool bCompactWidth = players[player]->bUseCompactGUIWidth(); | |||
| 11741 | const bool twoPrompts = bCompactWidth || (players[player]->bUseCompactGUIHeight() && !players[player]->bUseCompactGUIWidth() && *MainMenu::clipped_splitscreen); | |||
| 11742 | struct TextAndGlyphs | |||
| 11743 | { | |||
| 11744 | Frame::image_t* img1; | |||
| 11745 | Frame::image_t* img2; | |||
| 11746 | Field* div; | |||
| 11747 | Field* text; | |||
| 11748 | }; | |||
| 11749 | std::vector<TextAndGlyphs> textAndGlyphs; | |||
| 11750 | if ( twoPrompts ) | |||
| 11751 | { | |||
| 11752 | help_left->setText(Language::get(4315)); | |||
| 11753 | help_center->setDisabled(true); | |||
| 11754 | help_center_div->setDisabled(true); | |||
| 11755 | help_right->setText(Language::get(4316)); | |||
| 11756 | ||||
| 11757 | textAndGlyphs.push_back(TextAndGlyphs{ LogPageUp, LogPageDown, help_left_div, help_left}); | |||
| 11758 | textAndGlyphs.push_back(TextAndGlyphs{ LogScrollUp, LogScrollDown, help_right_div, help_right }); | |||
| 11759 | } | |||
| 11760 | else | |||
| 11761 | { | |||
| 11762 | help_left->setText(Language::get(4314)); | |||
| 11763 | help_center->setText(Language::get(4315)); | |||
| 11764 | help_right->setText(Language::get(4316)); | |||
| 11765 | ||||
| 11766 | textAndGlyphs.push_back(TextAndGlyphs{ LogHome, LogEnd, help_left_div, help_left }); | |||
| 11767 | textAndGlyphs.push_back(TextAndGlyphs{ LogPageUp, LogPageDown, help_center_div, help_center }); | |||
| 11768 | textAndGlyphs.push_back(TextAndGlyphs{ LogScrollUp, LogScrollDown, help_right_div, help_right }); | |||
| 11769 | } | |||
| 11770 | ||||
| 11771 | for ( auto& entry : textAndGlyphs ) | |||
| 11772 | { | |||
| 11773 | entry.div->setDisabled(entry.text->isDisabled()); | |||
| 11774 | ||||
| 11775 | entry.img1->disabled = entry.text->isDisabled(); | |||
| 11776 | if ( !entry.img1->disabled ) | |||
| 11777 | { | |||
| 11778 | std::string path = Input::inputs[player].getGlyphPathForBinding(entry.img1->name.c_str(), pressed); | |||
| 11779 | if ( auto glyph = Image::get(path.c_str()) ) | |||
| 11780 | { | |||
| 11781 | entry.img1->color = 0xffffffff; | |||
| 11782 | entry.img1->path = path; | |||
| 11783 | entry.img1->pos.w = (int)glyph->getWidth(); | |||
| 11784 | entry.img1->pos.h = (int)glyph->getHeight(); | |||
| 11785 | entry.img1->pos.y = (int)(h - 16 - entry.img1->pos.h / 2); | |||
| 11786 | } | |||
| 11787 | } | |||
| 11788 | ||||
| 11789 | entry.img2->disabled = entry.text->isDisabled(); | |||
| 11790 | if ( !entry.img2->disabled ) | |||
| 11791 | { | |||
| 11792 | std::string path = Input::inputs[player].getGlyphPathForBinding(entry.img2->name.c_str(), pressed); | |||
| 11793 | if ( auto glyph = Image::get(path.c_str()) ) | |||
| 11794 | { | |||
| 11795 | entry.img2->color = 0xffffffff; | |||
| 11796 | entry.img2->path = path; | |||
| 11797 | entry.img2->pos.w = (int)glyph->getWidth(); | |||
| 11798 | entry.img2->pos.h = (int)glyph->getHeight(); | |||
| 11799 | entry.img2->pos.y = (int)(h - 16 - entry.img2->pos.h / 2); | |||
| 11800 | } | |||
| 11801 | } | |||
| 11802 | if ( entry.text->isDisabled() ) | |||
| 11803 | { | |||
| 11804 | continue; | |||
| 11805 | } | |||
| 11806 | ||||
| 11807 | if ( entry.text == help_left ) | |||
| 11808 | { | |||
| 11809 | entry.img1->pos.x = 8; | |||
| 11810 | SDL_Rect divPos = entry.div->getSize(); | |||
| 11811 | divPos.x = entry.img1->pos.x + entry.img1->pos.w + 4; | |||
| 11812 | if ( auto textGet = entry.div->getTextObject() ) | |||
| 11813 | { | |||
| 11814 | divPos.w = textGet->getWidth(); | |||
| 11815 | } | |||
| 11816 | entry.div->setSize(divPos); | |||
| 11817 | ||||
| 11818 | entry.img2->pos.x = divPos.x + divPos.w + 4; | |||
| 11819 | SDL_Rect textPos = entry.text->getSize(); | |||
| 11820 | textPos.x = entry.img2->pos.x + entry.img2->pos.w + 8; | |||
| 11821 | entry.text->setSize(textPos); | |||
| 11822 | } | |||
| 11823 | else if ( entry.text == help_center ) | |||
| 11824 | { | |||
| 11825 | int totalWidth = entry.img1->pos.w + entry.img2->pos.w; | |||
| 11826 | SDL_Rect divPos = entry.div->getSize(); | |||
| 11827 | if ( auto textGet = entry.div->getTextObject() ) | |||
| 11828 | { | |||
| 11829 | divPos.w = textGet->getWidth(); | |||
| 11830 | } | |||
| 11831 | SDL_Rect textPos = entry.text->getSize(); | |||
| 11832 | if ( auto textGet = entry.text->getTextObject() ) | |||
| 11833 | { | |||
| 11834 | textPos.w = textGet->getWidth(); | |||
| 11835 | } | |||
| 11836 | totalWidth += 4 + 4 + divPos.w + 8 + textPos.w; | |||
| 11837 | int startx = w / 2 - (totalWidth / 2); | |||
| 11838 | if ( startx % 2 == 1 ) { ++startx; } // even alignment | |||
| 11839 | ||||
| 11840 | entry.img1->pos.x = startx; | |||
| 11841 | divPos.x = entry.img1->pos.x + entry.img1->pos.w + 4; | |||
| 11842 | entry.div->setSize(divPos); | |||
| 11843 | ||||
| 11844 | entry.img2->pos.x = divPos.x + divPos.w + 4; | |||
| 11845 | textPos.x = entry.img2->pos.x + entry.img2->pos.w + 8; | |||
| 11846 | entry.text->setSize(textPos); | |||
| 11847 | } | |||
| 11848 | else if ( entry.text == help_right ) | |||
| 11849 | { | |||
| 11850 | int totalWidth = entry.img1->pos.w + entry.img2->pos.w; | |||
| 11851 | SDL_Rect divPos = entry.div->getSize(); | |||
| 11852 | if ( auto textGet = entry.div->getTextObject() ) | |||
| 11853 | { | |||
| 11854 | divPos.w = textGet->getWidth(); | |||
| 11855 | } | |||
| 11856 | SDL_Rect textPos = entry.text->getSize(); | |||
| 11857 | if ( auto textGet = entry.text->getTextObject() ) | |||
| 11858 | { | |||
| 11859 | textPos.w = textGet->getWidth(); | |||
| 11860 | } | |||
| 11861 | totalWidth += 4 + 4 + divPos.w + 8 + textPos.w; | |||
| 11862 | int startx = w - 8 - totalWidth; | |||
| 11863 | if ( startx % 2 == 1 ) { --startx; } // even alignment | |||
| 11864 | ||||
| 11865 | entry.img1->pos.x = startx; | |||
| 11866 | divPos.x = entry.img1->pos.x + entry.img1->pos.w + 4; | |||
| 11867 | entry.div->setSize(divPos); | |||
| 11868 | ||||
| 11869 | entry.img2->pos.x = divPos.x + divPos.w + 4; | |||
| 11870 | textPos.x = entry.img2->pos.x + entry.img2->pos.w + 8; | |||
| 11871 | entry.text->setSize(textPos); | |||
| 11872 | } | |||
| 11873 | } | |||
| 11874 | ||||
| 11875 | auto subframe = frame->findFrame("subframe"); assert(subframe)(static_cast<void> (0)); | |||
| 11876 | auto subframe_size = subframe->getActualSize(); | |||
| 11877 | /*auto fields = subframe->getFields(); | |||
| 11878 | if ( fields.size() > 0 ) | |||
| 11879 | { | |||
| 11880 | SDL_Rect fieldPos = fields[fields.size() - 1]->getSize(); | |||
| 11881 | if ( fieldPos.y + fieldPos.h > subframe_size.h ) | |||
| 11882 | { | |||
| 11883 | subframe_size.h += (fieldPos.y + fieldPos.h - subframe_size.h); | |||
| 11884 | subframe_size.y += (fieldPos.y + fieldPos.h - subframe_size.h); | |||
| 11885 | subframe->setActualSize(subframe_size); | |||
| 11886 | } | |||
| 11887 | }*/ | |||
| 11888 | ||||
| 11889 | if (Input::inputs[player].consumeBinaryToggle("LogHome")) { | |||
| 11890 | Input::inputs[player].consumeBindingsSharedWithBinding("LogHome"); | |||
| 11891 | subframe_size.x = 0; | |||
| 11892 | subframe_size.y = 0; | |||
| 11893 | subframe->setActualSize(subframe_size); | |||
| 11894 | } | |||
| 11895 | if (Input::inputs[player].consumeBinaryToggle("LogEnd")) { | |||
| 11896 | Input::inputs[player].consumeBindingsSharedWithBinding("LogEnd"); | |||
| 11897 | const int limit = subframe_size.w > w ? | |||
| 11898 | subframe_size.h - subframe->getSize().h + 16: | |||
| 11899 | subframe_size.h - subframe->getSize().h; | |||
| 11900 | subframe_size.x = 0; | |||
| 11901 | subframe_size.y = std::max(0, limit); | |||
| 11902 | subframe->setActualSize(subframe_size); | |||
| 11903 | } | |||
| 11904 | if (Input::inputs[player].consumeBinaryToggle("LogPageUp")) { | |||
| 11905 | Input::inputs[player].consumeBindingsSharedWithBinding("LogPageUp"); | |||
| 11906 | subframe_size.y -= subframe->getSize().h; | |||
| 11907 | subframe_size.y = std::max(0, subframe_size.y); | |||
| 11908 | subframe->setActualSize(subframe_size); | |||
| 11909 | } | |||
| 11910 | if (Input::inputs[player].consumeBinaryToggle("LogPageDown")) { | |||
| 11911 | Input::inputs[player].consumeBindingsSharedWithBinding("LogPageDown"); | |||
| 11912 | subframe_size.y += subframe->getSize().h; | |||
| 11913 | const int limit = subframe_size.w > w ? | |||
| 11914 | subframe_size.h - subframe->getSize().h + 16: | |||
| 11915 | subframe_size.h - subframe->getSize().h; | |||
| 11916 | subframe_size.y = std::min(std::max(0, limit), subframe_size.y); | |||
| 11917 | subframe->setActualSize(subframe_size); | |||
| 11918 | } | |||
| 11919 | if ( Input::inputs[player].consumeBinaryToggle("LogClose") ) { | |||
| 11920 | Input::inputs[player].consumeBindingsSharedWithBinding("LogClose"); | |||
| 11921 | if ( players[player]->messageZone.logWindow ) { | |||
| 11922 | Player::soundCancel(); | |||
| 11923 | players[player]->messageZone.logWindow->removeSelf(); | |||
| 11924 | players[player]->messageZone.logWindow = nullptr; | |||
| 11925 | if ( players[player]->gui_mode == GUI_MODE_NONE ) { | |||
| 11926 | players[player]->shootmode = true; | |||
| 11927 | } | |||
| 11928 | else | |||
| 11929 | { | |||
| 11930 | players[player]->GUI.returnToPreviousActiveModule(); | |||
| 11931 | } | |||
| 11932 | } | |||
| 11933 | } | |||
| 11934 | ||||
| 11935 | if ( Frame::image_t* closeGlyph = frame->findImage("close glyph") ) | |||
| 11936 | { | |||
| 11937 | closeGlyph->disabled = true; | |||
| 11938 | if ( inputs.hasController(player) && !inputs.getVirtualMouse(player)->draw_cursor ) | |||
| 11939 | { | |||
| 11940 | Button* closeBtn = frame->findButton("close"); | |||
| 11941 | if (closeBtn) | |||
| 11942 | { | |||
| 11943 | SDL_Rect closeBtnPos = closeBtn->getSize(); | |||
| 11944 | closeBtn->setSize(closeBtnPos); | |||
| 11945 | ||||
| 11946 | closeGlyph->path = Input::inputs[player].getGlyphPathForBinding("LogClose"); | |||
| 11947 | if ( auto imgGet = Image::get(closeGlyph->path.c_str()) ) | |||
| 11948 | { | |||
| 11949 | closeGlyph->pos.w = imgGet->getWidth(); | |||
| 11950 | closeGlyph->pos.h = imgGet->getHeight(); | |||
| 11951 | closeGlyph->disabled = false; | |||
| 11952 | } | |||
| 11953 | closeGlyph->pos.x = closeBtn->getSize().x + closeBtn->getSize().w / 2 - closeGlyph->pos.w / 2; | |||
| 11954 | if ( closeGlyph->pos.x % 2 == 1 ) | |||
| 11955 | { | |||
| 11956 | ++closeGlyph->pos.x; | |||
| 11957 | } | |||
| 11958 | closeGlyph->pos.y = closeBtn->getSize().y + closeBtn->getSize().h - 4; | |||
| 11959 | } | |||
| 11960 | } | |||
| 11961 | } | |||
| 11962 | }); | |||
| 11963 | ||||
| 11964 | // frame images | |||
| 11965 | { | |||
| 11966 | frame->addImage( | |||
| 11967 | SDL_Rect{0, 0, 16, 32}, | |||
| 11968 | 0xffffffff, | |||
| 11969 | "*#images/ui/MapAndLog/Hover_TL00.png", | |||
| 11970 | "TL"); | |||
| 11971 | frame->addImage( | |||
| 11972 | SDL_Rect{16, 0, w - 32, 32}, | |||
| 11973 | 0xffffffff, | |||
| 11974 | "*#images/ui/MapAndLog/Hover_T00.png", | |||
| 11975 | "T"); | |||
| 11976 | frame->addImage( | |||
| 11977 | SDL_Rect{w - 16, 0, 16, 32}, | |||
| 11978 | 0xffffffff, | |||
| 11979 | "*#images/ui/MapAndLog/Hover_TR00.png", | |||
| 11980 | "TR"); | |||
| 11981 | auto L = frame->addImage( | |||
| 11982 | SDL_Rect{0, 32, 4, h - 64}, | |||
| 11983 | 0xffffffff, | |||
| 11984 | "*#images/ui/MapAndLog/Hover_L00.png", | |||
| 11985 | "L"); | |||
| 11986 | L->ontop = true; | |||
| 11987 | auto R = frame->addImage( | |||
| 11988 | SDL_Rect{w - 4, 32, 4, h - 64}, | |||
| 11989 | 0xffffffff, | |||
| 11990 | "*#images/ui/MapAndLog/Hover_R00.png", | |||
| 11991 | "R"); | |||
| 11992 | R->ontop = true; | |||
| 11993 | frame->addImage( | |||
| 11994 | SDL_Rect{0, h - 32, 16, 32}, | |||
| 11995 | 0xffffffff, | |||
| 11996 | "*#images/ui/MapAndLog/Hover_BL01.png", | |||
| 11997 | "BL"); | |||
| 11998 | frame->addImage( | |||
| 11999 | SDL_Rect{16, h - 32, w - 32, 32}, | |||
| 12000 | 0xffffffff, | |||
| 12001 | "*#images/ui/MapAndLog/Hover_B01.png", | |||
| 12002 | "B"); | |||
| 12003 | frame->addImage( | |||
| 12004 | SDL_Rect{w - 16, h - 32, 16, 32}, | |||
| 12005 | 0xffffffff, | |||
| 12006 | "*#images/ui/MapAndLog/Hover_BR01.png", | |||
| 12007 | "BR"); | |||
| 12008 | } | |||
| 12009 | ||||
| 12010 | auto subframe = frame->addFrame("subframe"); | |||
| 12011 | subframe->setScrollWithLeftControls(false); | |||
| 12012 | subframe->setSize(SDL_Rect{0, 32, w, h - 64}); | |||
| 12013 | subframe->setActualSize(SDL_Rect{0, 0, w, 4}); | |||
| 12014 | subframe->setBorderColor(makeColor(22, 24, 29, 255)); | |||
| 12015 | subframe->setSliderColor(makeColor(44, 48, 58, 255)); | |||
| 12016 | subframe->setColor(makeColor(0, 0, 0, 0)); | |||
| 12017 | subframe->setScrollBarsEnabled(true); | |||
| 12018 | //subframe->setBorder(2); | |||
| 12019 | subframe->setBorder(0); | |||
| 12020 | ||||
| 12021 | for (auto node = messages.first; node != nullptr; node = node->next) { | |||
| 12022 | auto string = (string_t*)node->element; | |||
| 12023 | if ( string->player == player ) | |||
| 12024 | { | |||
| 12025 | addMessageToLogWindow(player, string); | |||
| 12026 | } | |||
| 12027 | } | |||
| 12028 | ||||
| 12029 | auto label = frame->addField("label", 64); | |||
| 12030 | label->setSize(SDL_Rect{16, 0, w - 40, 32}); | |||
| 12031 | label->setHJustify(Field::justify_t::LEFT); | |||
| 12032 | label->setVJustify(Field::justify_t::CENTER); | |||
| 12033 | label->setFont(bigfont_outline); | |||
| 12034 | label->setText(Language::get(5967)); | |||
| 12035 | ||||
| 12036 | auto closeGlyph = frame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, | |||
| 12037 | "", "close glyph"); | |||
| 12038 | closeGlyph->disabled = true; | |||
| 12039 | closeGlyph->ontop = true; | |||
| 12040 | ||||
| 12041 | auto close_button = frame->addButton("close"); | |||
| 12042 | close_button->setSize(SDL_Rect{frame->getSize().w - 30, 4, 26, 26}); | |||
| 12043 | close_button->setColor(makeColor(255, 255, 255, 255)); | |||
| 12044 | close_button->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 12045 | close_button->setText("X"); | |||
| 12046 | close_button->setFont(smallfont_outline); | |||
| 12047 | close_button->setHideGlyphs(true); | |||
| 12048 | close_button->setHideKeyboardGlyphs(true); | |||
| 12049 | close_button->setHideSelectors(true); | |||
| 12050 | close_button->setMenuConfirmControlType(0); | |||
| 12051 | close_button->setBackground("*#images/ui/Shop/Button_X_00.png"); | |||
| 12052 | close_button->setBackgroundHighlighted("*#images/ui/Shop/Button_XHigh_00.png"); | |||
| 12053 | close_button->setBackgroundActivated("*#images/ui/Shop/Button_XPress_00.png"); | |||
| 12054 | close_button->setTextHighlightColor(makeColor(201, 162, 100, 255)); | |||
| 12055 | close_button->setCallback([](Button& button){ | |||
| 12056 | const int player = button.getOwner(); | |||
| 12057 | players[player]->messageZone.logWindow = nullptr; | |||
| 12058 | auto parent = static_cast<Frame*>(button.getParent()); | |||
| 12059 | parent->removeSelf(); | |||
| 12060 | if (players[player]->gui_mode == GUI_MODE_NONE) { | |||
| 12061 | players[player]->shootmode = true; | |||
| 12062 | } | |||
| 12063 | else | |||
| 12064 | { | |||
| 12065 | players[player]->GUI.returnToPreviousActiveModule(); | |||
| 12066 | } | |||
| 12067 | Player::soundCancel(); | |||
| 12068 | }); | |||
| 12069 | close_button->setDrawCallback([](const Widget& widget, SDL_Rect rect) | |||
| 12070 | { | |||
| 12071 | Button* button = (Button*)(&widget); | |||
| 12072 | const int player = button->getOwner(); | |||
| 12073 | if ( inputs.getVirtualMouse(player)->draw_cursor ) | |||
| 12074 | { | |||
| 12075 | if ( button->isHighlighted() ) | |||
| 12076 | { | |||
| 12077 | players[player]->GUI.setHoveringOverModuleButton(Player::GUI_t::MODULE_LOG); | |||
| 12078 | if ( players[player]->GUI.activeModule != Player::GUI_t::MODULE_LOG ) | |||
| 12079 | { | |||
| 12080 | players[player]->GUI.activateModule(Player::GUI_t::MODULE_LOG); | |||
| 12081 | } | |||
| 12082 | SDL_Rect pos = button->getAbsoluteSize(); | |||
| 12083 | // make sure to adjust absolute size to camera viewport | |||
| 12084 | pos.x -= players[player]->camera_virtualx1(); | |||
| 12085 | pos.y -= players[player]->camera_virtualy1(); | |||
| 12086 | players[player]->hud.setCursorDisabled(false); | |||
| 12087 | players[player]->hud.updateCursorAnimation(pos.x - 1, pos.y - 1, pos.w, pos.h, inputs.getVirtualMouse(player)->draw_cursor); | |||
| 12088 | } | |||
| 12089 | } | |||
| 12090 | }); | |||
| 12091 | ||||
| 12092 | auto help_left = frame->addField("help_left", 128); | |||
| 12093 | help_left->setSize(SDL_Rect{0, h - 32, w, 32}); | |||
| 12094 | help_left->setHJustify(Field::justify_t::LEFT); | |||
| 12095 | help_left->setVJustify(Field::justify_t::CENTER); | |||
| 12096 | help_left->setFont(smallfont_outline); | |||
| 12097 | help_left->setDisabled(true); | |||
| 12098 | ||||
| 12099 | auto help_left_div = frame->addField("help_left_div", 32); | |||
| 12100 | help_left_div->setSize(SDL_Rect{ 0, h - 32, w, 32 }); | |||
| 12101 | help_left_div->setHJustify(Field::justify_t::LEFT); | |||
| 12102 | help_left_div->setVJustify(Field::justify_t::CENTER); | |||
| 12103 | help_left_div->setFont(smallfont_outline); | |||
| 12104 | help_left_div->setDisabled(true); | |||
| 12105 | help_left_div->setText("/"); | |||
| 12106 | ||||
| 12107 | frame->addImage(SDL_Rect{0,0,0,0}, 0, | |||
| 12108 | "images/system/white.png", "LogHome"); | |||
| 12109 | frame->addImage(SDL_Rect{0,0,0,0}, 0, | |||
| 12110 | "images/system/white.png", "LogEnd"); | |||
| 12111 | ||||
| 12112 | auto help_center = frame->addField("help_center", 128); | |||
| 12113 | help_center->setSize(SDL_Rect{0, h - 32, w, 32}); | |||
| 12114 | help_center->setHJustify(Field::justify_t::LEFT); | |||
| 12115 | help_center->setVJustify(Field::justify_t::CENTER); | |||
| 12116 | help_center->setFont(smallfont_outline); | |||
| 12117 | help_center->setDisabled(true); | |||
| 12118 | ||||
| 12119 | auto help_center_div = frame->addField("help_center_div", 32); | |||
| 12120 | help_center_div->setSize(SDL_Rect{ 0, h - 32, w, 32 }); | |||
| 12121 | help_center_div->setHJustify(Field::justify_t::LEFT); | |||
| 12122 | help_center_div->setVJustify(Field::justify_t::CENTER); | |||
| 12123 | help_center_div->setFont(smallfont_outline); | |||
| 12124 | help_center_div->setDisabled(true); | |||
| 12125 | help_center_div->setText("/"); | |||
| 12126 | ||||
| 12127 | frame->addImage(SDL_Rect{0,0,0,0}, 0, | |||
| 12128 | "images/system/white.png", "LogPageUp"); | |||
| 12129 | frame->addImage(SDL_Rect{0,0,0,0}, 0, | |||
| 12130 | "images/system/white.png", "LogPageDown"); | |||
| 12131 | ||||
| 12132 | auto help_right = frame->addField("help_right", 128); | |||
| 12133 | help_right->setSize(SDL_Rect{0, h - 32, w - 4, 32}); | |||
| 12134 | help_right->setHJustify(Field::justify_t::RIGHT); | |||
| 12135 | help_right->setVJustify(Field::justify_t::CENTER); | |||
| 12136 | help_right->setFont(smallfont_outline); | |||
| 12137 | help_right->setDisabled(true); | |||
| 12138 | ||||
| 12139 | auto help_right_div = frame->addField("help_right_div", 32); | |||
| 12140 | help_right_div->setSize(SDL_Rect{ 0, h - 32, w, 32 }); | |||
| 12141 | help_right_div->setHJustify(Field::justify_t::LEFT); | |||
| 12142 | help_right_div->setVJustify(Field::justify_t::CENTER); | |||
| 12143 | help_right_div->setFont(smallfont_outline); | |||
| 12144 | help_right_div->setDisabled(true); | |||
| 12145 | help_right_div->setText("/"); | |||
| 12146 | ||||
| 12147 | frame->addImage(SDL_Rect{0,0,0,0}, 0, | |||
| 12148 | "images/system/white.png", "LogScrollUp"); | |||
| 12149 | frame->addImage(SDL_Rect{0,0,0,0}, 0, | |||
| 12150 | "images/system/white.png", "LogScrollDown"); | |||
| 12151 | } | |||
| 12152 | ||||
| 12153 | std::map<std::string, std::pair<std::string, std::string>> Player::CharacterSheet_t::mapDisplayNamesDescriptions; | |||
| 12154 | std::string Player::CharacterSheet_t::defaultString = ""; | |||
| 12155 | std::map<std::string, std::string> Player::CharacterSheet_t::hoverTextStrings; | |||
| 12156 | void Player::CharacterSheet_t::loadCharacterSheetJSON() | |||
| 12157 | { | |||
| 12158 | if ( !PHYSFS_getRealDir("/data/charsheet.json") ) | |||
| 12159 | { | |||
| 12160 | printlog("[JSON]: Error: Could not find file: data/charsheet.json"); | |||
| 12161 | } | |||
| 12162 | else | |||
| 12163 | { | |||
| 12164 | std::string inputPath = PHYSFS_getRealDir("/data/charsheet.json"); | |||
| 12165 | inputPath.append("/data/charsheet.json"); | |||
| 12166 | ||||
| 12167 | File* fp = FileIO::open(inputPath.c_str(), "rb"); | |||
| 12168 | if ( !fp ) | |||
| 12169 | { | |||
| 12170 | printlog("[JSON]: Error: Could not open json file %s", inputPath.c_str()); | |||
| 12171 | } | |||
| 12172 | else | |||
| 12173 | { | |||
| 12174 | char buf[65536]; | |||
| 12175 | int count = fp->read(buf, sizeof(buf[0]), sizeof(buf)); | |||
| 12176 | buf[count] = '\0'; | |||
| 12177 | rapidjson::StringStream is(buf); | |||
| 12178 | FileIO::close(fp); | |||
| 12179 | rapidjson::Document d; | |||
| 12180 | d.ParseStream(is); | |||
| 12181 | if ( !d.HasMember("version") ) | |||
| 12182 | { | |||
| 12183 | printlog("[JSON]: Error: No 'version' value in json file, or JSON syntax incorrect! %s", inputPath.c_str()); | |||
| 12184 | } | |||
| 12185 | else | |||
| 12186 | { | |||
| 12187 | if ( d.HasMember("level_strings") ) | |||
| 12188 | { | |||
| 12189 | mapDisplayNamesDescriptions.clear(); | |||
| 12190 | for ( rapidjson::Value::ConstMemberIterator itr = d["level_strings"].MemberBegin(); | |||
| 12191 | itr != d["level_strings"].MemberEnd(); ++itr ) | |||
| 12192 | { | |||
| 12193 | std::string name = ""; | |||
| 12194 | std::string desc = ""; | |||
| 12195 | if ( itr->value.HasMember("display_name") ) | |||
| 12196 | { | |||
| 12197 | name = itr->value["display_name"].GetString(); | |||
| 12198 | } | |||
| 12199 | if ( itr->value.HasMember("description") ) | |||
| 12200 | { | |||
| 12201 | desc = itr->value["description"].GetString(); | |||
| 12202 | } | |||
| 12203 | mapDisplayNamesDescriptions[itr->name.GetString()] = std::make_pair(name, desc); | |||
| 12204 | } | |||
| 12205 | } | |||
| 12206 | if ( d.HasMember("hover_text") ) | |||
| 12207 | { | |||
| 12208 | hoverTextStrings.clear(); | |||
| 12209 | for ( rapidjson::Value::ConstMemberIterator itr = d["hover_text"].MemberBegin(); | |||
| 12210 | itr != d["hover_text"].MemberEnd(); ++itr ) | |||
| 12211 | { | |||
| 12212 | if ( itr->value.IsObject() ) | |||
| 12213 | { | |||
| 12214 | for ( rapidjson::Value::ConstMemberIterator inner_itr = itr->value.MemberBegin(); | |||
| 12215 | inner_itr != itr->value.MemberEnd(); ++inner_itr ) | |||
| 12216 | { | |||
| 12217 | hoverTextStrings[inner_itr->name.GetString()] = inner_itr->value.GetString(); | |||
| 12218 | } | |||
| 12219 | } | |||
| 12220 | else | |||
| 12221 | { | |||
| 12222 | hoverTextStrings[itr->name.GetString()] = itr->value.GetString(); | |||
| 12223 | } | |||
| 12224 | } | |||
| 12225 | } | |||
| 12226 | } | |||
| 12227 | } | |||
| 12228 | } | |||
| 12229 | } | |||
| 12230 | ||||
| 12231 | const int NUM_CHARSHEET_TOOLTIP_BACKING_FRAMES = 9; | |||
| 12232 | const int NUM_CHARSHEET_TOOLTIP_TEXT_FIELDS = 16; | |||
| 12233 | std::map<int, Field*> characterSheetTooltipTextFields[MAXPLAYERS4]; | |||
| 12234 | std::map<int, Frame*> characterSheetTooltipTextBackingFrames[MAXPLAYERS4]; | |||
| 12235 | ||||
| 12236 | static void charsheet_deselect_fn(Widget& widget) { | |||
| 12237 | if ( widget.isSelected() | |||
| 12238 | && players[widget.getOwner()]->GUI.activeModule != Player::GUI_t::MODULE_CHARACTERSHEET | |||
| 12239 | && !inputs.getVirtualMouse(widget.getOwner())->draw_cursor ) | |||
| 12240 | { | |||
| 12241 | widget.deselect(); | |||
| 12242 | } | |||
| 12243 | }; | |||
| 12244 | ||||
| 12245 | void Player::CharacterSheet_t::createCharacterSheet() | |||
| 12246 | { | |||
| 12247 | char name[32]; | |||
| 12248 | snprintf(name, sizeof(name), "player sheet %d", player.playernum); | |||
| 12249 | if ( !gameUIFrame[player.playernum]->findFrame(name) ) | |||
| 12250 | { | |||
| 12251 | characterSheetTooltipTextFields[player.playernum].clear(); | |||
| 12252 | characterSheetTooltipTextBackingFrames[player.playernum].clear(); | |||
| 12253 | ||||
| 12254 | Frame* sheetFrame = gameUIFrame[player.playernum]->addFrame(name); | |||
| 12255 | sheetFrame->setHollow(true); | |||
| 12256 | sheetFrame->setBorder(0); | |||
| 12257 | sheetFrame->setOwner(player.playernum); | |||
| 12258 | sheetFrame->setSize(SDL_Rect{ players[player.playernum]->camera_virtualx1(), | |||
| 12259 | players[player.playernum]->camera_virtualy1(), | |||
| 12260 | Frame::virtualScreenX, | |||
| 12261 | Frame::virtualScreenY }); | |||
| 12262 | this->sheetFrame = sheetFrame; | |||
| 12263 | ||||
| 12264 | const int bgWidth = 208; | |||
| 12265 | const int leftAlignX = sheetFrame->getSize().w - bgWidth; | |||
| 12266 | { | |||
| 12267 | Frame* fullscreenBg = sheetFrame->addFrame("sheet bg fullscreen"); | |||
| 12268 | fullscreenBg->setSize(SDL_Rect{ leftAlignX, | |||
| 12269 | 0, 208, Frame::virtualScreenY }); | |||
| 12270 | // if splitscreen 3/4 - disable the fullscreen background + title text. | |||
| 12271 | fullscreenBg->addImage(SDL_Rect{ 0, 0, fullscreenBg->getSize().w, 360 }, | |||
| 12272 | 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_Window_01A_Top.png", "bg image"); | |||
| 12273 | ||||
| 12274 | const char* titleFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 12275 | auto characterSheetTitleText = fullscreenBg->addField("character sheet title text", 32); | |||
| 12276 | characterSheetTitleText->setFont(titleFont); | |||
| 12277 | characterSheetTitleText->setSize(SDL_Rect{ 6, 177, 202, 32 }); | |||
| 12278 | characterSheetTitleText->setText(Language::get(5968)); | |||
| 12279 | characterSheetTitleText->setVJustify(Field::justify_t::CENTER); | |||
| 12280 | characterSheetTitleText->setHJustify(Field::justify_t::CENTER); | |||
| 12281 | } | |||
| 12282 | ||||
| 12283 | // log / map buttons | |||
| 12284 | { | |||
| 12285 | const char* buttonFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 12286 | SDL_Rect buttonFramePos{ leftAlignX + 9, 6, 196, 82 }; | |||
| 12287 | auto buttonFrame = sheetFrame->addFrame("log map buttons"); | |||
| 12288 | buttonFrame->setSize(buttonFramePos); | |||
| 12289 | buttonFrame->setDrawCallback([](const Widget& widget, SDL_Rect pos) { | |||
| 12290 | auto frame = (Frame*)(&widget); | |||
| 12291 | std::vector<const char*> buttons = { | |||
| 12292 | "map button", | |||
| 12293 | "log button" | |||
| 12294 | }; | |||
| 12295 | for ( auto button : buttons ) | |||
| 12296 | { | |||
| 12297 | if ( auto b = frame->findButton(button) ) | |||
| 12298 | { | |||
| 12299 | if ( players[frame->getOwner()]->characterSheet.sheetDisplayType == CHARSHEET_DISPLAY_NORMAL ) | |||
| 12300 | { | |||
| 12301 | b->setBackgroundHighlighted("*#images/ui/CharSheet/HUD_CharSheet_ButtonHigh_00.png"); | |||
| 12302 | b->setBackground("*#images/ui/CharSheet/HUD_CharSheet_Button_00.png"); | |||
| 12303 | b->setBackgroundActivated("*#images/ui/CharSheet/HUD_CharSheet_ButtonPress_00.png"); | |||
| 12304 | } | |||
| 12305 | else | |||
| 12306 | { | |||
| 12307 | b->setBackgroundHighlighted("*#images/ui/CharSheet/HUD_CharSheet_ButtonHighCompact_00.png"); | |||
| 12308 | b->setBackground("*#images/ui/CharSheet/HUD_CharSheet_ButtonCompact_00.png"); | |||
| 12309 | b->setBackgroundActivated("*#images/ui/CharSheet/HUD_CharSheet_ButtonCompactPress_00.png"); | |||
| 12310 | } | |||
| 12311 | } | |||
| 12312 | } | |||
| 12313 | }); | |||
| 12314 | ||||
| 12315 | SDL_Rect buttonPos{ 0, 0, buttonFramePos.w, 40 }; | |||
| 12316 | auto mapButton = buttonFrame->addButton("map button"); | |||
| 12317 | mapButton->setText(Language::get(4069)); | |||
| 12318 | mapButton->setFont(buttonFont); | |||
| 12319 | mapButton->setBackground("*#images/ui/CharSheet/HUD_CharSheet_Button_00.png"); | |||
| 12320 | mapButton->setSize(buttonPos); | |||
| 12321 | mapButton->setHideGlyphs(true); | |||
| 12322 | mapButton->setHideKeyboardGlyphs(true); | |||
| 12323 | mapButton->setHideSelectors(true); | |||
| 12324 | mapButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12325 | mapButton->setColor(makeColor(255, 255, 255, 255)); | |||
| 12326 | mapButton->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 12327 | mapButton->setCallback([](Button& button) { | |||
| 12328 | openMapWindow(button.getOwner()); | |||
| 12329 | if ( players[button.getOwner()]->minimap.mapWindow ) { | |||
| 12330 | button.deselect(); | |||
| 12331 | } | |||
| 12332 | }); | |||
| 12333 | mapButton->setTickCallback(charsheet_deselect_fn); | |||
| 12334 | ||||
| 12335 | auto mapSelector = buttonFrame->addFrame("map button selector"); | |||
| 12336 | mapSelector->setSize(buttonPos); | |||
| 12337 | mapSelector->setHollow(true); | |||
| 12338 | //mapSelector->setClickable(true); | |||
| 12339 | ||||
| 12340 | buttonPos.y = buttonPos.y + buttonPos.h + 2; | |||
| 12341 | auto logButton = buttonFrame->addButton("log button"); | |||
| 12342 | logButton->setText(Language::get(4070)); | |||
| 12343 | logButton->setFont(buttonFont); | |||
| 12344 | logButton->setBackground("*#images/ui/CharSheet/HUD_CharSheet_Button_00.png"); | |||
| 12345 | logButton->setSize(buttonPos); | |||
| 12346 | logButton->setHideGlyphs(true); | |||
| 12347 | logButton->setHideKeyboardGlyphs(true); | |||
| 12348 | logButton->setHideSelectors(true); | |||
| 12349 | logButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12350 | logButton->setColor(makeColor(255, 255, 255, 255)); | |||
| 12351 | logButton->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 12352 | logButton->setCallback([](Button& button) { | |||
| 12353 | openLogWindow(button.getOwner()); | |||
| 12354 | }); | |||
| 12355 | logButton->setTickCallback(charsheet_deselect_fn); | |||
| 12356 | ||||
| 12357 | auto logSelector = buttonFrame->addFrame("log button selector"); | |||
| 12358 | logSelector->setSize(buttonPos); | |||
| 12359 | logSelector->setHollow(true); | |||
| 12360 | //logSelector->setClickable(true); | |||
| 12361 | } | |||
| 12362 | ||||
| 12363 | // game timer | |||
| 12364 | { | |||
| 12365 | const char* timerFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 12366 | Uint32 timerTextColor = makeColor(188, 154, 114, 255); | |||
| 12367 | ||||
| 12368 | Frame* timerFrame = sheetFrame->addFrame("game timer"); | |||
| 12369 | timerFrame->setSize(SDL_Rect{ leftAlignX + 36, 90, 142, 26 }); | |||
| 12370 | timerFrame->setDrawCallback([](const Widget& widget, SDL_Rect pos) { | |||
| 12371 | auto frame = (Frame*)(&widget); | |||
| 12372 | auto timerToggleImg = frame->findImage("timer icon img"); | |||
| 12373 | auto timerSelector = frame->findButton("timer selector"); | |||
| 12374 | if ( timerToggleImg && timerSelector ) | |||
| 12375 | { | |||
| 12376 | if ( !players[frame->getOwner()]->characterSheet.showGameTimerAlways ) | |||
| 12377 | { | |||
| 12378 | if ( timerSelector->isCurrentlyPressed() ) | |||
| 12379 | { | |||
| 12380 | timerToggleImg->path = "images/ui/CharSheet/HUD_Button_Timer_PressOff00.png"; | |||
| 12381 | } | |||
| 12382 | else if ( timerSelector->isHighlighted() || (!inputs.getVirtualMouse(widget.getOwner())->draw_cursor && timerSelector->isSelected()) ) | |||
| 12383 | { | |||
| 12384 | timerToggleImg->path = "images/ui/CharSheet/HUD_Button_Timer_SelectOff00.png"; | |||
| 12385 | } | |||
| 12386 | else | |||
| 12387 | { | |||
| 12388 | timerToggleImg->path = "images/ui/CharSheet/HUD_Button_Timer_UnselectOff00.png"; | |||
| 12389 | } | |||
| 12390 | } | |||
| 12391 | else | |||
| 12392 | { | |||
| 12393 | if ( timerSelector->isCurrentlyPressed() ) | |||
| 12394 | { | |||
| 12395 | timerToggleImg->path = "images/ui/CharSheet/HUD_Button_Timer_PressOn00.png"; | |||
| 12396 | } | |||
| 12397 | else if ( timerSelector->isHighlighted() || (!inputs.getVirtualMouse(widget.getOwner())->draw_cursor && timerSelector->isSelected()) ) | |||
| 12398 | { | |||
| 12399 | timerToggleImg->path = "images/ui/CharSheet/HUD_Button_Timer_SelectOn00.png"; | |||
| 12400 | } | |||
| 12401 | else | |||
| 12402 | { | |||
| 12403 | timerToggleImg->path = "images/ui/CharSheet/HUD_Button_Timer_UnselectOn00.png"; | |||
| 12404 | } | |||
| 12405 | } | |||
| 12406 | } | |||
| 12407 | }); | |||
| 12408 | auto timerToggleImg = timerFrame->addImage(SDL_Rect{ 0, 0, 26, 26 }, 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_Button_Timer_SelectOff00.png", "timer icon img"); | |||
| 12409 | auto timerImg = timerFrame->addImage(SDL_Rect{ 30, 0, 112, 26 }, 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_Timer_Backing_00.png", "timer bg img"); | |||
| 12410 | auto timerText = timerFrame->addField("timer text", 32); | |||
| 12411 | timerText->setFont(timerFont); | |||
| 12412 | ||||
| 12413 | auto timerButton = timerFrame->addButton("timer selector"); | |||
| 12414 | timerButton->setSize(SDL_Rect{ 0, 0, timerToggleImg->pos.w + timerImg->pos.w, 26 }); | |||
| 12415 | timerButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 12416 | timerButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 12417 | timerButton->setHideGlyphs(true); | |||
| 12418 | timerButton->setHideKeyboardGlyphs(true); | |||
| 12419 | timerButton->setHideSelectors(true); | |||
| 12420 | timerButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12421 | timerButton->setCallback([](Button& button) { | |||
| 12422 | bool& bShowTimer = players[button.getOwner()]->characterSheet.showGameTimerAlways; | |||
| 12423 | bShowTimer = !bShowTimer; | |||
| 12424 | if ( bShowTimer ) | |||
| 12425 | { | |||
| 12426 | Player::soundActivate(); | |||
| 12427 | } | |||
| 12428 | else | |||
| 12429 | { | |||
| 12430 | Player::soundCancel(); | |||
| 12431 | } | |||
| 12432 | }); | |||
| 12433 | timerButton->setTickCallback(charsheet_deselect_fn); | |||
| 12434 | ||||
| 12435 | SDL_Rect textPos = timerImg->pos; | |||
| 12436 | textPos.x += 12; | |||
| 12437 | timerText->setSize(textPos); | |||
| 12438 | timerText->setVJustify(Field::justify_t::CENTER); | |||
| 12439 | timerText->setText("00:92:30:89"); | |||
| 12440 | timerText->setColor(timerTextColor); | |||
| 12441 | } | |||
| 12442 | ||||
| 12443 | // skills button | |||
| 12444 | { | |||
| 12445 | const char* skillsFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 12446 | Frame* skillsButtonFrame = sheetFrame->addFrame("skills button frame"); | |||
| 12447 | skillsButtonFrame->setSize(SDL_Rect{ leftAlignX + 14, 360 - 8 - 42, 186, 42 }); | |||
| 12448 | auto skillsButton = skillsButtonFrame->addButton("skills button"); | |||
| 12449 | skillsButton->setText(Language::get(4074)); | |||
| 12450 | skillsButton->setFont(skillsFont); | |||
| 12451 | skillsButton->setBackground("*#images/ui/CharSheet/HUD_CharSheet_ButtonWide_00.png"); | |||
| 12452 | skillsButton->setBackgroundActivated("*#images/ui/CharSheet/HUD_CharSheet_ButtonWidePress_00.png"); | |||
| 12453 | skillsButton->setBackgroundHighlighted("*#images/ui/CharSheet/HUD_CharSheet_ButtonWideHigh_00.png"); | |||
| 12454 | skillsButton->setSize(SDL_Rect{ 0, 0, skillsButtonFrame->getSize().w, skillsButtonFrame->getSize().h }); | |||
| 12455 | skillsButton->setHideGlyphs(true); | |||
| 12456 | skillsButton->setHideKeyboardGlyphs(true); | |||
| 12457 | skillsButton->setHideSelectors(true); | |||
| 12458 | skillsButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12459 | skillsButton->setColor(makeColor(255, 255, 255, 255)); | |||
| 12460 | skillsButton->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 12461 | skillsButton->setCallback([](Button& button) { | |||
| 12462 | players[button.getOwner()]->skillSheet.openSkillSheet(); | |||
| 12463 | }); | |||
| 12464 | skillsButton->setTickCallback(charsheet_deselect_fn); | |||
| 12465 | } | |||
| 12466 | ||||
| 12467 | // dungeon floor and level descriptor | |||
| 12468 | { | |||
| 12469 | const char* dungeonFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 12470 | Uint32 dungeonTextColor = makeColor(188, 154, 114, 255); | |||
| 12471 | Frame* dungeonFloorFrame = sheetFrame->addFrame("dungeon floor frame"); | |||
| 12472 | ||||
| 12473 | dungeonFloorFrame->setSize(SDL_Rect{ leftAlignX + 6, 118, 202, 52 }); | |||
| 12474 | auto dungeonButton = dungeonFloorFrame->addButton("dungeon floor selector"); | |||
| 12475 | dungeonButton->setSize(SDL_Rect{ 6, 6, 190, 44 }); | |||
| 12476 | dungeonButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 12477 | dungeonButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 12478 | dungeonButton->setHideGlyphs(true); | |||
| 12479 | dungeonButton->setHideKeyboardGlyphs(true); | |||
| 12480 | dungeonButton->setHideSelectors(true); | |||
| 12481 | dungeonButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12482 | dungeonButton->setTickCallback(charsheet_deselect_fn); | |||
| 12483 | ||||
| 12484 | auto floorNameText = dungeonFloorFrame->addField("dungeon name text", 32); | |||
| 12485 | floorNameText->setFont(dungeonFont); | |||
| 12486 | floorNameText->setSize(SDL_Rect{ 10, 0, 182, 26 }); | |||
| 12487 | floorNameText->setText(""); | |||
| 12488 | floorNameText->setVJustify(Field::justify_t::CENTER); | |||
| 12489 | floorNameText->setHJustify(Field::justify_t::CENTER); | |||
| 12490 | floorNameText->setColor(dungeonTextColor); | |||
| 12491 | ||||
| 12492 | auto floorLevelText = dungeonFloorFrame->addField("dungeon level text", 32); | |||
| 12493 | floorLevelText->setFont(dungeonFont); | |||
| 12494 | floorLevelText->setSize(SDL_Rect{ 10, 26, 182, 26 }); | |||
| 12495 | floorLevelText->setText(""); | |||
| 12496 | floorLevelText->setVJustify(Field::justify_t::CENTER); | |||
| 12497 | floorLevelText->setHJustify(Field::justify_t::CENTER); | |||
| 12498 | floorLevelText->setColor(dungeonTextColor); | |||
| 12499 | } | |||
| 12500 | ||||
| 12501 | Frame* characterFrame = sheetFrame->addFrame("character info"); | |||
| 12502 | const char* infoFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 12503 | characterFrame->setSize(SDL_Rect{ leftAlignX, 206, bgWidth, 116 }); | |||
| 12504 | characterFrame->setHollow(true); | |||
| 12505 | Uint32 infoTextColor = makeColor(188, 154, 114, 255); | |||
| 12506 | Uint32 classTextColor = makeColor(74, 66, 207, 255); | |||
| 12507 | ||||
| 12508 | sheetFrame->addImage(SDL_Rect{ characterFrame->getSize().x, characterFrame->getSize().y - 60, | |||
| 12509 | 214, 170 }, 0xFFFFFFFF, | |||
| 12510 | "*#images/ui/CharSheet/HUD_CharSheet_Window_01A_TopCompact.png", "character info compact img"); | |||
| 12511 | ||||
| 12512 | Frame* characterInnerFrame = characterFrame->addFrame("character info inner frame"); | |||
| 12513 | characterInnerFrame->setSize(SDL_Rect{ 6, 0, 202, 104 }); | |||
| 12514 | { | |||
| 12515 | //characterInnerFrame->addImage(SDL_Rect{ 0, 0, characterInnerFrame->getSize().w, characterInnerFrame->getSize().h }, 0xFFFFFFFF, | |||
| 12516 | // "*#images/ui/CharSheet/HUD_CharSheet_Window_01A_TopTmp.png", "character info tmp img"); | |||
| 12517 | ||||
| 12518 | ||||
| 12519 | SDL_Rect characterTextPos{ 2, 0, 198, 24 }; | |||
| 12520 | auto nameText = characterInnerFrame->addField("character name text", 32); | |||
| 12521 | nameText->setFont(infoFont); | |||
| 12522 | nameText->setSize(SDL_Rect{ characterTextPos.x, | |||
| 12523 | characterTextPos.y, | |||
| 12524 | characterTextPos.w, | |||
| 12525 | characterTextPos.h }); | |||
| 12526 | nameText->setText("Slartibartfast"); | |||
| 12527 | nameText->setVJustify(Field::justify_t::CENTER); | |||
| 12528 | nameText->setHJustify(Field::justify_t::CENTER); | |||
| 12529 | nameText->setColor(infoTextColor); | |||
| 12530 | ||||
| 12531 | /*characterInnerFrame->addImage(SDL_Rect{ 2, 2, 198, 20 }, makeColor(255, 255, 255, 64), | |||
| 12532 | "images/system/white.png", "character name frame");*/ | |||
| 12533 | //characterInnerFrame->addFrame("character name selector")->setSize(SDL_Rect{ 2, 2, 198, 20 }); | |||
| 12534 | ||||
| 12535 | characterTextPos.x = 8; | |||
| 12536 | characterTextPos.w = 190; | |||
| 12537 | characterTextPos.y = 52; | |||
| 12538 | characterTextPos.h = 26; | |||
| 12539 | auto levelText = characterInnerFrame->addField("character level text", 32); | |||
| 12540 | levelText->setFont(infoFont); | |||
| 12541 | levelText->setSize(SDL_Rect{ characterTextPos.x, | |||
| 12542 | characterTextPos.y, | |||
| 12543 | characterTextPos.w, | |||
| 12544 | characterTextPos.h }); | |||
| 12545 | levelText->setText(""); | |||
| 12546 | levelText->setVJustify(Field::justify_t::CENTER); | |||
| 12547 | levelText->setColor(infoTextColor); | |||
| 12548 | ||||
| 12549 | /*characterInnerFrame->addImage(SDL_Rect{ 4, 54, 194, 22 }, makeColor(255, 255, 255, 64), | |||
| 12550 | "images/system/white.png", "character level frame");*/ | |||
| 12551 | auto classButton = characterInnerFrame->addButton("character class selector"); | |||
| 12552 | classButton->setSize(SDL_Rect{ 4, 54, 194, 22 }); | |||
| 12553 | classButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 12554 | classButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 12555 | classButton->setHideGlyphs(true); | |||
| 12556 | classButton->setHideKeyboardGlyphs(true); | |||
| 12557 | classButton->setHideSelectors(true); | |||
| 12558 | classButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12559 | classButton->setTickCallback(charsheet_deselect_fn); | |||
| 12560 | ||||
| 12561 | characterTextPos.x = 8; | |||
| 12562 | characterTextPos.w = 190; | |||
| 12563 | characterTextPos.y = 52; | |||
| 12564 | characterTextPos.h = 26; | |||
| 12565 | auto classText = characterInnerFrame->addField("character class text", 32); | |||
| 12566 | classText->setFont(infoFont); | |||
| 12567 | classText->setSize(SDL_Rect{ characterTextPos.x, | |||
| 12568 | characterTextPos.y, | |||
| 12569 | characterTextPos.w, | |||
| 12570 | characterTextPos.h }); | |||
| 12571 | classText->setText(""); | |||
| 12572 | classText->setVJustify(Field::justify_t::CENTER); | |||
| 12573 | classText->setHJustify(Field::justify_t::LEFT); | |||
| 12574 | classText->setTextColor(classTextColor); | |||
| 12575 | ||||
| 12576 | characterTextPos.x = 4; | |||
| 12577 | characterTextPos.w = 194; | |||
| 12578 | characterTextPos.y = 26; | |||
| 12579 | characterTextPos.h = 26; | |||
| 12580 | auto raceText = characterInnerFrame->addField("character race text", 32); | |||
| 12581 | raceText->setFont(infoFont); | |||
| 12582 | raceText->setSize(SDL_Rect{ characterTextPos.x, | |||
| 12583 | characterTextPos.y, | |||
| 12584 | characterTextPos.w, | |||
| 12585 | characterTextPos.h }); | |||
| 12586 | raceText->setText(""); | |||
| 12587 | raceText->setVJustify(Field::justify_t::CENTER); | |||
| 12588 | raceText->setHJustify(Field::justify_t::CENTER); | |||
| 12589 | raceText->setColor(infoTextColor); | |||
| 12590 | ||||
| 12591 | auto sexImg = characterInnerFrame->addImage( | |||
| 12592 | SDL_Rect{ characterTextPos.x + characterTextPos.w - 40, characterTextPos.y - 4, 16, 28 }, 0xFFFFFFFF, | |||
| 12593 | "*#images/ui/CharSheet/HUD_CharSheet_Sex_M_01.png", "character sex img"); | |||
| 12594 | ||||
| 12595 | /*characterInnerFrame->addImage(SDL_Rect{ 4, 28, 194, 22 }, makeColor(255, 255, 255, 64), | |||
| 12596 | "images/system/white.png", "character race frame");*/ | |||
| 12597 | auto raceButton = characterInnerFrame->addButton("character race selector"); | |||
| 12598 | raceButton->setSize(SDL_Rect{ 4, 28, 194, 22 }); | |||
| 12599 | raceButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 12600 | raceButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 12601 | raceButton->setHideGlyphs(true); | |||
| 12602 | raceButton->setHideKeyboardGlyphs(true); | |||
| 12603 | raceButton->setHideSelectors(true); | |||
| 12604 | raceButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12605 | raceButton->setTickCallback(charsheet_deselect_fn); | |||
| 12606 | ||||
| 12607 | characterTextPos.x = 4; | |||
| 12608 | characterTextPos.w = 194; | |||
| 12609 | characterTextPos.y = 78; | |||
| 12610 | characterTextPos.h = 26; | |||
| 12611 | auto goldTitleText = characterInnerFrame->addField("gold text title", 8); | |||
| 12612 | goldTitleText->setFont(infoFont); | |||
| 12613 | goldTitleText->setSize(SDL_Rect{ 48, characterTextPos.y, 52, characterTextPos.h }); | |||
| 12614 | goldTitleText->setText(Language::get(5969)); | |||
| 12615 | goldTitleText->setVJustify(Field::justify_t::CENTER); | |||
| 12616 | goldTitleText->setColor(infoTextColor); | |||
| 12617 | ||||
| 12618 | auto goldText = characterInnerFrame->addField("gold text", 32); | |||
| 12619 | goldText->setFont(infoFont); | |||
| 12620 | goldText->setSize(SDL_Rect{ 92, characterTextPos.y, 88, characterTextPos.h }); | |||
| 12621 | goldText->setText("0"); | |||
| 12622 | goldText->setVJustify(Field::justify_t::CENTER); | |||
| 12623 | goldText->setHJustify(Field::justify_t::CENTER); | |||
| 12624 | goldText->setColor(infoTextColor); | |||
| 12625 | ||||
| 12626 | auto goldImg = characterInnerFrame->addImage(SDL_Rect{ 24, characterTextPos.y - 4, 20, 28 }, | |||
| 12627 | 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_ButtonMoney_00.png", "gold img"); | |||
| 12628 | ||||
| 12629 | /*characterInnerFrame->addImage(SDL_Rect{ 24, 80, 156, 22 }, makeColor(255, 255, 255, 64), | |||
| 12630 | "images/system/white.png", "character gold frame");*/ | |||
| 12631 | auto goldButton = characterInnerFrame->addButton("character gold selector"); | |||
| 12632 | goldButton->setSize(SDL_Rect{ 22, 80, 158, 22 }); | |||
| 12633 | goldButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 12634 | goldButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 12635 | goldButton->setHideGlyphs(true); | |||
| 12636 | goldButton->setHideKeyboardGlyphs(true); | |||
| 12637 | goldButton->setHideSelectors(true); | |||
| 12638 | goldButton->setMenuConfirmControlType(0); | |||
| 12639 | goldButton->setTickCallback(charsheet_deselect_fn); | |||
| 12640 | } | |||
| 12641 | ||||
| 12642 | { | |||
| 12643 | Frame* statsFrame = sheetFrame->addFrame("stats"); | |||
| 12644 | const int statsFrameHeight = 182; | |||
| 12645 | statsFrame->setSize(SDL_Rect{ leftAlignX, 344, bgWidth, statsFrameHeight }); | |||
| 12646 | statsFrame->addImage(SDL_Rect{ 0, 0, statsFrame->getSize().w, statsFrame->getSize().h }, | |||
| 12647 | 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_Window_01B_BotA.png", "stats bg img"); | |||
| 12648 | ||||
| 12649 | Frame* statsInnerFrame = statsFrame->addFrame("stats inner frame"); | |||
| 12650 | statsInnerFrame->setSize(SDL_Rect{ 0, 0, statsFrame->getSize().w, statsFrame->getSize().h }); | |||
| 12651 | ||||
| 12652 | SDL_Rect iconPos{ 20, 8, 24, 24 }; | |||
| 12653 | const int headingLeftX = iconPos.x + iconPos.w + 4; | |||
| 12654 | const int baseStatLeftX = headingLeftX + 32; | |||
| 12655 | const int modifiedStatLeftX = baseStatLeftX + 64; | |||
| 12656 | SDL_Rect textPos{ headingLeftX, iconPos.y, 40, iconPos.h }; | |||
| 12657 | Uint32 statTextColor = hudColors.characterSheetNeutral; | |||
| 12658 | ||||
| 12659 | const char* statFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 12660 | textPos.y = iconPos.y + 1; | |||
| 12661 | statsInnerFrame->addImage(iconPos, 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_STR_00.png", "str icon"); | |||
| 12662 | { | |||
| 12663 | auto textBase = statsInnerFrame->addField("str text title", 8); | |||
| 12664 | textBase->setVJustify(Field::justify_t::CENTER); | |||
| 12665 | textBase->setFont(statFont); | |||
| 12666 | textPos.x = headingLeftX; | |||
| 12667 | textBase->setSize(textPos); | |||
| 12668 | textBase->setText(Language::get(5300)); | |||
| 12669 | textBase->setColor(statTextColor); | |||
| 12670 | auto textStat = statsInnerFrame->addField("str text stat", 32); | |||
| 12671 | textStat->setVJustify(Field::justify_t::CENTER); | |||
| 12672 | textStat->setHJustify(Field::justify_t::CENTER); | |||
| 12673 | textStat->setFont(statFont); | |||
| 12674 | textPos.x = baseStatLeftX; | |||
| 12675 | textStat->setSize(textPos); | |||
| 12676 | textStat->setText("0"); | |||
| 12677 | textStat->setColor(statTextColor); | |||
| 12678 | auto textStatModified = statsInnerFrame->addField("str text modified", 32); | |||
| 12679 | textStatModified->setVJustify(Field::justify_t::CENTER); | |||
| 12680 | textStatModified->setHJustify(Field::justify_t::CENTER); | |||
| 12681 | textStatModified->setFont(statFont); | |||
| 12682 | textPos.x = modifiedStatLeftX; | |||
| 12683 | textStatModified->setSize(textPos); | |||
| 12684 | textStatModified->setText(""); | |||
| 12685 | textStatModified->setColor(statTextColor); | |||
| 12686 | ||||
| 12687 | auto statButton = statsInnerFrame->addButton("str button"); | |||
| 12688 | statButton->setSize(SDL_Rect{ 12, iconPos.y + 2, statsFrame->getSize().w - 34, iconPos.h - 2 }); | |||
| 12689 | statButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 12690 | statButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 12691 | statButton->setHideGlyphs(true); | |||
| 12692 | statButton->setHideKeyboardGlyphs(true); | |||
| 12693 | statButton->setHideSelectors(true); | |||
| 12694 | statButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12695 | statButton->setTickCallback(charsheet_deselect_fn); | |||
| 12696 | } | |||
| 12697 | const int rowSpacing = 4; | |||
| 12698 | iconPos.y += iconPos.h + rowSpacing; | |||
| 12699 | textPos.y = iconPos.y + 1; | |||
| 12700 | statsInnerFrame->addImage(iconPos, 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_DEX_00.png", "dex icon"); | |||
| 12701 | { | |||
| 12702 | auto textBase = statsInnerFrame->addField("dex text title", 8); | |||
| 12703 | textBase->setVJustify(Field::justify_t::CENTER); | |||
| 12704 | textBase->setFont(statFont); | |||
| 12705 | textPos.x = headingLeftX; | |||
| 12706 | textBase->setSize(textPos); | |||
| 12707 | textBase->setText(Language::get(5301)); | |||
| 12708 | textBase->setColor(statTextColor); | |||
| 12709 | auto textStat = statsInnerFrame->addField("dex text stat", 32); | |||
| 12710 | textStat->setVJustify(Field::justify_t::CENTER); | |||
| 12711 | textStat->setHJustify(Field::justify_t::CENTER); | |||
| 12712 | textStat->setFont(statFont); | |||
| 12713 | textPos.x = baseStatLeftX; | |||
| 12714 | textStat->setSize(textPos); | |||
| 12715 | textStat->setText("0"); | |||
| 12716 | textStat->setColor(statTextColor); | |||
| 12717 | auto textStatModified = statsInnerFrame->addField("dex text modified", 32); | |||
| 12718 | textStatModified->setVJustify(Field::justify_t::CENTER); | |||
| 12719 | textStatModified->setHJustify(Field::justify_t::CENTER); | |||
| 12720 | textStatModified->setFont(statFont); | |||
| 12721 | textPos.x = modifiedStatLeftX; | |||
| 12722 | textStatModified->setSize(textPos); | |||
| 12723 | textStatModified->setText("2"); | |||
| 12724 | textStatModified->setColor(statTextColor); | |||
| 12725 | ||||
| 12726 | auto statButton = statsInnerFrame->addButton("dex button"); | |||
| 12727 | statButton->setSize(SDL_Rect{ 12, iconPos.y + 2, statsFrame->getSize().w - 34, iconPos.h - 2 }); | |||
| 12728 | statButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 12729 | statButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 12730 | statButton->setHideGlyphs(true); | |||
| 12731 | statButton->setHideKeyboardGlyphs(true); | |||
| 12732 | statButton->setHideSelectors(true); | |||
| 12733 | statButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12734 | statButton->setTickCallback(charsheet_deselect_fn); | |||
| 12735 | } | |||
| 12736 | ||||
| 12737 | iconPos.y += iconPos.h + rowSpacing; | |||
| 12738 | textPos.y = iconPos.y + 1; | |||
| 12739 | statsInnerFrame->addImage(iconPos, 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_CON_00.png", "con icon"); | |||
| 12740 | { | |||
| 12741 | auto textBase = statsInnerFrame->addField("con text title", 8); | |||
| 12742 | textBase->setVJustify(Field::justify_t::CENTER); | |||
| 12743 | textBase->setFont(statFont); | |||
| 12744 | textPos.x = headingLeftX; | |||
| 12745 | textBase->setSize(textPos); | |||
| 12746 | textBase->setText(Language::get(5302)); | |||
| 12747 | textBase->setColor(statTextColor); | |||
| 12748 | auto textStat = statsInnerFrame->addField("con text stat", 32); | |||
| 12749 | textStat->setVJustify(Field::justify_t::CENTER); | |||
| 12750 | textStat->setHJustify(Field::justify_t::CENTER); | |||
| 12751 | textStat->setFont(statFont); | |||
| 12752 | textPos.x = baseStatLeftX; | |||
| 12753 | textStat->setSize(textPos); | |||
| 12754 | textStat->setText("0"); | |||
| 12755 | textStat->setColor(statTextColor); | |||
| 12756 | auto textStatModified = statsInnerFrame->addField("con text modified", 32); | |||
| 12757 | textStatModified->setVJustify(Field::justify_t::CENTER); | |||
| 12758 | textStatModified->setHJustify(Field::justify_t::CENTER); | |||
| 12759 | textStatModified->setFont(statFont); | |||
| 12760 | textPos.x = modifiedStatLeftX; | |||
| 12761 | textStatModified->setSize(textPos); | |||
| 12762 | textStatModified->setText(""); | |||
| 12763 | textStatModified->setColor(statTextColor); | |||
| 12764 | ||||
| 12765 | auto statButton = statsInnerFrame->addButton("con button"); | |||
| 12766 | statButton->setSize(SDL_Rect{ 12, iconPos.y + 2, statsFrame->getSize().w - 34, iconPos.h - 2 }); | |||
| 12767 | statButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 12768 | statButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 12769 | statButton->setHideGlyphs(true); | |||
| 12770 | statButton->setHideKeyboardGlyphs(true); | |||
| 12771 | statButton->setHideSelectors(true); | |||
| 12772 | statButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12773 | statButton->setTickCallback(charsheet_deselect_fn); | |||
| 12774 | } | |||
| 12775 | ||||
| 12776 | iconPos.y += iconPos.h + rowSpacing; | |||
| 12777 | textPos.y = iconPos.y + 1; | |||
| 12778 | statsInnerFrame->addImage(iconPos, 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_INT_00.png", "int icon"); | |||
| 12779 | { | |||
| 12780 | auto textBase = statsInnerFrame->addField("int text title", 8); | |||
| 12781 | textBase->setVJustify(Field::justify_t::CENTER); | |||
| 12782 | textBase->setFont(statFont); | |||
| 12783 | textPos.x = headingLeftX; | |||
| 12784 | textBase->setSize(textPos); | |||
| 12785 | textBase->setText(Language::get(5303)); | |||
| 12786 | textBase->setColor(statTextColor); | |||
| 12787 | auto textStat = statsInnerFrame->addField("int text stat", 32); | |||
| 12788 | textStat->setVJustify(Field::justify_t::CENTER); | |||
| 12789 | textStat->setHJustify(Field::justify_t::CENTER); | |||
| 12790 | textStat->setFont(statFont); | |||
| 12791 | textPos.x = baseStatLeftX; | |||
| 12792 | textStat->setSize(textPos); | |||
| 12793 | textStat->setText("0"); | |||
| 12794 | textStat->setColor(statTextColor); | |||
| 12795 | auto textStatModified = statsInnerFrame->addField("int text modified", 32); | |||
| 12796 | textStatModified->setVJustify(Field::justify_t::CENTER); | |||
| 12797 | textStatModified->setHJustify(Field::justify_t::CENTER); | |||
| 12798 | textStatModified->setFont(statFont); | |||
| 12799 | textPos.x = modifiedStatLeftX; | |||
| 12800 | textStatModified->setSize(textPos); | |||
| 12801 | textStatModified->setText(""); | |||
| 12802 | textStatModified->setColor(statTextColor); | |||
| 12803 | ||||
| 12804 | auto statButton = statsInnerFrame->addButton("int button"); | |||
| 12805 | statButton->setSize(SDL_Rect{ 12, iconPos.y + 2, statsFrame->getSize().w - 34, iconPos.h - 2 }); | |||
| 12806 | statButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 12807 | statButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 12808 | statButton->setHideGlyphs(true); | |||
| 12809 | statButton->setHideKeyboardGlyphs(true); | |||
| 12810 | statButton->setHideSelectors(true); | |||
| 12811 | statButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12812 | statButton->setTickCallback(charsheet_deselect_fn); | |||
| 12813 | } | |||
| 12814 | ||||
| 12815 | iconPos.y += iconPos.h + rowSpacing; | |||
| 12816 | textPos.y = iconPos.y + 1; | |||
| 12817 | statsInnerFrame->addImage(iconPos, 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_PER_00.png", "per icon"); | |||
| 12818 | { | |||
| 12819 | auto textBase = statsInnerFrame->addField("per text title", 8); | |||
| 12820 | textBase->setVJustify(Field::justify_t::CENTER); | |||
| 12821 | textBase->setFont(statFont); | |||
| 12822 | textPos.x = headingLeftX; | |||
| 12823 | textBase->setSize(textPos); | |||
| 12824 | textBase->setText(Language::get(5304)); | |||
| 12825 | textBase->setColor(statTextColor); | |||
| 12826 | auto textStat = statsInnerFrame->addField("per text stat", 32); | |||
| 12827 | textStat->setVJustify(Field::justify_t::CENTER); | |||
| 12828 | textStat->setHJustify(Field::justify_t::CENTER); | |||
| 12829 | textStat->setFont(statFont); | |||
| 12830 | textPos.x = baseStatLeftX; | |||
| 12831 | textStat->setSize(textPos); | |||
| 12832 | textStat->setText("0"); | |||
| 12833 | textStat->setColor(statTextColor); | |||
| 12834 | auto textStatModified = statsInnerFrame->addField("per text modified", 32); | |||
| 12835 | textStatModified->setVJustify(Field::justify_t::CENTER); | |||
| 12836 | textStatModified->setHJustify(Field::justify_t::CENTER); | |||
| 12837 | textStatModified->setFont(statFont); | |||
| 12838 | textPos.x = modifiedStatLeftX; | |||
| 12839 | textStatModified->setSize(textPos); | |||
| 12840 | textStatModified->setText(""); | |||
| 12841 | textStatModified->setColor(statTextColor); | |||
| 12842 | ||||
| 12843 | auto statButton = statsInnerFrame->addButton("per button"); | |||
| 12844 | statButton->setSize(SDL_Rect{ 12, iconPos.y + 2, statsFrame->getSize().w - 34, iconPos.h - 2 }); | |||
| 12845 | statButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 12846 | statButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 12847 | statButton->setHideGlyphs(true); | |||
| 12848 | statButton->setHideKeyboardGlyphs(true); | |||
| 12849 | statButton->setHideSelectors(true); | |||
| 12850 | statButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12851 | statButton->setTickCallback(charsheet_deselect_fn); | |||
| 12852 | } | |||
| 12853 | ||||
| 12854 | iconPos.y += iconPos.h + rowSpacing; | |||
| 12855 | textPos.y = iconPos.y + 1; | |||
| 12856 | statsInnerFrame->addImage(iconPos, 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_CHA_00.png", "chr icon"); | |||
| 12857 | { | |||
| 12858 | auto textBase = statsInnerFrame->addField("chr text title", 8); | |||
| 12859 | textBase->setVJustify(Field::justify_t::CENTER); | |||
| 12860 | textBase->setFont(statFont); | |||
| 12861 | textPos.x = headingLeftX; | |||
| 12862 | textBase->setSize(textPos); | |||
| 12863 | textBase->setText(Language::get(5305)); | |||
| 12864 | textBase->setColor(statTextColor); | |||
| 12865 | auto textStat = statsInnerFrame->addField("chr text stat", 32); | |||
| 12866 | textStat->setVJustify(Field::justify_t::CENTER); | |||
| 12867 | textStat->setHJustify(Field::justify_t::CENTER); | |||
| 12868 | textStat->setFont(statFont); | |||
| 12869 | textPos.x = baseStatLeftX; | |||
| 12870 | textStat->setSize(textPos); | |||
| 12871 | textStat->setText("0"); | |||
| 12872 | textStat->setColor(statTextColor); | |||
| 12873 | auto textStatModified = statsInnerFrame->addField("chr text modified", 32); | |||
| 12874 | textStatModified->setVJustify(Field::justify_t::CENTER); | |||
| 12875 | textStatModified->setHJustify(Field::justify_t::CENTER); | |||
| 12876 | textStatModified->setFont(statFont); | |||
| 12877 | textPos.x = modifiedStatLeftX; | |||
| 12878 | textStatModified->setSize(textPos); | |||
| 12879 | textStatModified->setText(""); | |||
| 12880 | textStatModified->setColor(statTextColor); | |||
| 12881 | ||||
| 12882 | auto statButton = statsInnerFrame->addButton("chr button"); | |||
| 12883 | statButton->setSize(SDL_Rect{ 12, iconPos.y + 2, statsFrame->getSize().w - 34, iconPos.h - 2 }); | |||
| 12884 | statButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 12885 | statButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 12886 | statButton->setHideGlyphs(true); | |||
| 12887 | statButton->setHideKeyboardGlyphs(true); | |||
| 12888 | statButton->setHideSelectors(true); | |||
| 12889 | statButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12890 | statButton->setTickCallback(charsheet_deselect_fn); | |||
| 12891 | } | |||
| 12892 | } | |||
| 12893 | ||||
| 12894 | { | |||
| 12895 | Frame* attributesFrame = sheetFrame->addFrame("attributes"); | |||
| 12896 | attributesFrame->setSize(SDL_Rect{ leftAlignX, 550, bgWidth, 182 }); | |||
| 12897 | ||||
| 12898 | attributesFrame->addImage(SDL_Rect{ 0, 0, attributesFrame->getSize().w, attributesFrame->getSize().h }, | |||
| 12899 | 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_Window_01B_BotB.png", "attributes bg img"); | |||
| 12900 | ||||
| 12901 | Frame* attributesInnerFrame = attributesFrame->addFrame("attributes inner frame"); | |||
| 12902 | attributesInnerFrame->setSize(SDL_Rect{ 0, 0, attributesFrame->getSize().w, attributesFrame->getSize().h }); | |||
| 12903 | ||||
| 12904 | SDL_Rect iconPos{ 20, 8, 24, 24 }; | |||
| 12905 | const int headingLeftX = iconPos.x + iconPos.w + 4; | |||
| 12906 | const int baseStatLeftX = headingLeftX + 48; | |||
| 12907 | SDL_Rect textPos{ headingLeftX, iconPos.y, 80, iconPos.h }; | |||
| 12908 | Uint32 statTextColor = hudColors.characterSheetNeutral; | |||
| 12909 | ||||
| 12910 | const char* attributeFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 12911 | textPos.y = iconPos.y + 1; | |||
| 12912 | attributesInnerFrame->addImage(iconPos, 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_ATT_00.png", "atk icon"); | |||
| 12913 | { | |||
| 12914 | auto textBase = attributesInnerFrame->addField("atk text title", 8); | |||
| 12915 | textBase->setVJustify(Field::justify_t::CENTER); | |||
| 12916 | textBase->setFont(attributeFont); | |||
| 12917 | textPos.x = headingLeftX; | |||
| 12918 | textBase->setSize(textPos); | |||
| 12919 | textBase->setText(Language::get(6093)); | |||
| 12920 | textBase->setColor(statTextColor); | |||
| 12921 | auto textStat = attributesInnerFrame->addField("atk text stat", 32); | |||
| 12922 | textStat->setVJustify(Field::justify_t::CENTER); | |||
| 12923 | textStat->setHJustify(Field::justify_t::CENTER); | |||
| 12924 | textStat->setFont(attributeFont); | |||
| 12925 | textPos.x = baseStatLeftX; | |||
| 12926 | textStat->setSize(textPos); | |||
| 12927 | textStat->setText("14"); | |||
| 12928 | textStat->setColor(statTextColor); | |||
| 12929 | ||||
| 12930 | auto attributeButton = attributesInnerFrame->addButton("atk button"); | |||
| 12931 | attributeButton->setSize(SDL_Rect{ 12, iconPos.y + 2, attributesFrame->getSize().w - 34, iconPos.h - 2 }); | |||
| 12932 | attributeButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 12933 | attributeButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 12934 | attributeButton->setHideGlyphs(true); | |||
| 12935 | attributeButton->setHideKeyboardGlyphs(true); | |||
| 12936 | attributeButton->setHideSelectors(true); | |||
| 12937 | attributeButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12938 | attributeButton->setTickCallback(charsheet_deselect_fn); | |||
| 12939 | } | |||
| 12940 | ||||
| 12941 | const int rowSpacing = 4; | |||
| 12942 | iconPos.y += iconPos.h + rowSpacing; | |||
| 12943 | textPos.y = iconPos.y + 1; | |||
| 12944 | attributesInnerFrame->addImage(iconPos, 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_AC_00.png", "ac icon"); | |||
| 12945 | { | |||
| 12946 | auto textBase = attributesInnerFrame->addField("ac text title", 8); | |||
| 12947 | textBase->setVJustify(Field::justify_t::CENTER); | |||
| 12948 | textBase->setFont(attributeFont); | |||
| 12949 | textPos.x = headingLeftX; | |||
| 12950 | textBase->setSize(textPos); | |||
| 12951 | textBase->setText(Language::get(6094)); | |||
| 12952 | textBase->setColor(statTextColor); | |||
| 12953 | auto textStat = attributesInnerFrame->addField("ac text stat", 32); | |||
| 12954 | textStat->setVJustify(Field::justify_t::CENTER); | |||
| 12955 | textStat->setHJustify(Field::justify_t::CENTER); | |||
| 12956 | textStat->setFont(attributeFont); | |||
| 12957 | textPos.x = baseStatLeftX; | |||
| 12958 | textStat->setSize(textPos); | |||
| 12959 | textStat->setText("3"); | |||
| 12960 | textStat->setColor(statTextColor); | |||
| 12961 | ||||
| 12962 | auto attributeButton = attributesInnerFrame->addButton("ac button"); | |||
| 12963 | attributeButton->setSize(SDL_Rect{ 12, iconPos.y + 2, attributesFrame->getSize().w - 34, iconPos.h - 2 }); | |||
| 12964 | attributeButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 12965 | attributeButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 12966 | attributeButton->setHideGlyphs(true); | |||
| 12967 | attributeButton->setHideKeyboardGlyphs(true); | |||
| 12968 | attributeButton->setHideSelectors(true); | |||
| 12969 | attributeButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 12970 | attributeButton->setTickCallback(charsheet_deselect_fn); | |||
| 12971 | } | |||
| 12972 | ||||
| 12973 | iconPos.y += iconPos.h + rowSpacing; | |||
| 12974 | textPos.y = iconPos.y + 1; | |||
| 12975 | attributesInnerFrame->addImage(iconPos, 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_SPWR_00.png", "pwr icon"); | |||
| 12976 | { | |||
| 12977 | auto textBase = attributesInnerFrame->addField("pwr text title", 8); | |||
| 12978 | textBase->setVJustify(Field::justify_t::CENTER); | |||
| 12979 | textBase->setFont(attributeFont); | |||
| 12980 | textPos.x = headingLeftX; | |||
| 12981 | textBase->setSize(textPos); | |||
| 12982 | textBase->setText(Language::get(6095)); | |||
| 12983 | textBase->setColor(statTextColor); | |||
| 12984 | auto textStat = attributesInnerFrame->addField("pwr text stat", 32); | |||
| 12985 | textStat->setVJustify(Field::justify_t::CENTER); | |||
| 12986 | textStat->setHJustify(Field::justify_t::CENTER); | |||
| 12987 | textStat->setFont(attributeFont); | |||
| 12988 | textPos.x = baseStatLeftX; | |||
| 12989 | textStat->setSize(textPos); | |||
| 12990 | textStat->setText("115%"); | |||
| 12991 | textStat->setColor(statTextColor); | |||
| 12992 | ||||
| 12993 | auto attributeButton = attributesInnerFrame->addButton("pow button"); | |||
| 12994 | attributeButton->setSize(SDL_Rect{ 12, iconPos.y + 2, attributesFrame->getSize().w - 34, iconPos.h - 2 }); | |||
| 12995 | attributeButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 12996 | attributeButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 12997 | attributeButton->setHideGlyphs(true); | |||
| 12998 | attributeButton->setHideKeyboardGlyphs(true); | |||
| 12999 | attributeButton->setHideSelectors(true); | |||
| 13000 | attributeButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 13001 | attributeButton->setTickCallback(charsheet_deselect_fn); | |||
| 13002 | } | |||
| 13003 | ||||
| 13004 | iconPos.y += iconPos.h + rowSpacing; | |||
| 13005 | textPos.y = iconPos.y + 1; | |||
| 13006 | attributesInnerFrame->addImage(iconPos, 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_RES_00.png", "res icon"); | |||
| 13007 | { | |||
| 13008 | auto textBase = attributesInnerFrame->addField("res text title", 8); | |||
| 13009 | textBase->setVJustify(Field::justify_t::CENTER); | |||
| 13010 | textBase->setFont(attributeFont); | |||
| 13011 | textPos.x = headingLeftX; | |||
| 13012 | textBase->setSize(textPos); | |||
| 13013 | textBase->setText(Language::get(6096)); | |||
| 13014 | textBase->setColor(statTextColor); | |||
| 13015 | auto textStat = attributesInnerFrame->addField("res text stat", 32); | |||
| 13016 | textStat->setVJustify(Field::justify_t::CENTER); | |||
| 13017 | textStat->setHJustify(Field::justify_t::CENTER); | |||
| 13018 | textStat->setFont(attributeFont); | |||
| 13019 | textPos.x = baseStatLeftX; | |||
| 13020 | textStat->setSize(textPos); | |||
| 13021 | textStat->setText("100%"); | |||
| 13022 | textStat->setColor(statTextColor); | |||
| 13023 | ||||
| 13024 | auto attributeButton = attributesInnerFrame->addButton("res button"); | |||
| 13025 | attributeButton->setSize(SDL_Rect{ 12, iconPos.y + 2, attributesFrame->getSize().w - 34, iconPos.h - 2 }); | |||
| 13026 | attributeButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 13027 | attributeButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 13028 | attributeButton->setHideGlyphs(true); | |||
| 13029 | attributeButton->setHideKeyboardGlyphs(true); | |||
| 13030 | attributeButton->setHideSelectors(true); | |||
| 13031 | attributeButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 13032 | attributeButton->setTickCallback(charsheet_deselect_fn); | |||
| 13033 | } | |||
| 13034 | ||||
| 13035 | iconPos.y += iconPos.h + rowSpacing; | |||
| 13036 | textPos.y = iconPos.y + 1; | |||
| 13037 | attributesInnerFrame->addImage(iconPos, 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_REGEN_00.png", "regen icon"); | |||
| 13038 | { | |||
| 13039 | auto textBase = attributesInnerFrame->addField("regen text title", 8); | |||
| 13040 | textBase->setVJustify(Field::justify_t::CENTER); | |||
| 13041 | textBase->setFont(attributeFont); | |||
| 13042 | textPos.x = headingLeftX; | |||
| 13043 | textBase->setSize(textPos); | |||
| 13044 | textBase->setText(Language::get(6097)); | |||
| 13045 | textBase->setColor(statTextColor); | |||
| 13046 | ||||
| 13047 | auto textDiv = attributesInnerFrame->addField("regen text divider", 4); | |||
| 13048 | textDiv->setVJustify(Field::justify_t::CENTER); | |||
| 13049 | textDiv->setHJustify(Field::justify_t::CENTER); | |||
| 13050 | textDiv->setFont(attributeFont); | |||
| 13051 | textPos.x = baseStatLeftX + 0; | |||
| 13052 | textDiv->setSize(textPos); | |||
| 13053 | textDiv->setText(" "); | |||
| 13054 | textDiv->setColor(statTextColor); | |||
| 13055 | ||||
| 13056 | SDL_Rect hpmpTextPos = textPos; | |||
| 13057 | const int middleX = (textPos.x + textPos.w / 2); | |||
| 13058 | auto textRegenHP = attributesInnerFrame->addField("regen text hp", 16); | |||
| 13059 | textRegenHP->setVJustify(Field::justify_t::CENTER); | |||
| 13060 | textRegenHP->setHJustify(Field::justify_t::RIGHT); | |||
| 13061 | textRegenHP->setFont(attributeFont); | |||
| 13062 | hpmpTextPos.x = middleX - 4 - hpmpTextPos.w; | |||
| 13063 | textRegenHP->setSize(hpmpTextPos); | |||
| 13064 | textRegenHP->setText("0.2"); | |||
| 13065 | textRegenHP->setColor(statTextColor); | |||
| 13066 | ||||
| 13067 | auto textRegenMP = attributesInnerFrame->addField("regen text mp", 16); | |||
| 13068 | textRegenMP->setVJustify(Field::justify_t::CENTER); | |||
| 13069 | textRegenMP->setHJustify(Field::justify_t::LEFT); | |||
| 13070 | textRegenMP->setFont(attributeFont); | |||
| 13071 | hpmpTextPos.x = middleX + 4; | |||
| 13072 | textRegenMP->setSize(hpmpTextPos); | |||
| 13073 | textRegenMP->setText("0.1"); | |||
| 13074 | textRegenMP->setColor(statTextColor); | |||
| 13075 | ||||
| 13076 | auto attributeButton = attributesInnerFrame->addButton("rgn button"); | |||
| 13077 | const int fullWidth = attributesFrame->getSize().w - 34 + 12; | |||
| 13078 | attributeButton->setSize(SDL_Rect{ 12, iconPos.y + 2, attributesFrame->getSize().w - 34 - 50, iconPos.h - 2 }); | |||
| 13079 | attributeButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 13080 | attributeButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 13081 | attributeButton->setHideGlyphs(true); | |||
| 13082 | attributeButton->setHideKeyboardGlyphs(true); | |||
| 13083 | attributeButton->setHideSelectors(true); | |||
| 13084 | attributeButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 13085 | attributeButton->setTickCallback(charsheet_deselect_fn); | |||
| 13086 | ||||
| 13087 | auto attributeButton2 = attributesInnerFrame->addButton("rgn mp button"); | |||
| 13088 | attributeButton2->setSize(SDL_Rect{ attributeButton->getSize().x + attributeButton->getSize().w, | |||
| 13089 | iconPos.y + 2, fullWidth - (attributeButton->getSize().x + attributeButton->getSize().w), iconPos.h - 2 }); | |||
| 13090 | attributeButton2->setColor(makeColor(0, 0, 0, 0)); | |||
| 13091 | attributeButton2->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 13092 | attributeButton2->setHideGlyphs(true); | |||
| 13093 | attributeButton2->setHideKeyboardGlyphs(true); | |||
| 13094 | attributeButton2->setHideSelectors(true); | |||
| 13095 | attributeButton2->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 13096 | attributeButton2->setTickCallback(charsheet_deselect_fn); | |||
| 13097 | } | |||
| 13098 | ||||
| 13099 | iconPos.y += iconPos.h + rowSpacing; | |||
| 13100 | textPos.y = iconPos.y + 1; | |||
| 13101 | attributesInnerFrame->addImage(iconPos, 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_WGT_00.png", "weight icon"); | |||
| 13102 | { | |||
| 13103 | auto textBase = attributesInnerFrame->addField("weight text title", 8); | |||
| 13104 | textBase->setVJustify(Field::justify_t::CENTER); | |||
| 13105 | textBase->setFont(attributeFont); | |||
| 13106 | textPos.x = headingLeftX; | |||
| 13107 | textBase->setSize(textPos); | |||
| 13108 | textBase->setText(Language::get(6098)); | |||
| 13109 | textBase->setColor(statTextColor); | |||
| 13110 | auto textStat = attributesInnerFrame->addField("weight text stat", 32); | |||
| 13111 | textStat->setVJustify(Field::justify_t::CENTER); | |||
| 13112 | textStat->setHJustify(Field::justify_t::CENTER); | |||
| 13113 | textStat->setFont(attributeFont); | |||
| 13114 | textPos.x = baseStatLeftX; | |||
| 13115 | textStat->setSize(textPos); | |||
| 13116 | textStat->setText("120"); | |||
| 13117 | textStat->setColor(statTextColor); | |||
| 13118 | ||||
| 13119 | auto attributeButton = attributesInnerFrame->addButton("wgt button"); | |||
| 13120 | attributeButton->setSize(SDL_Rect{ 12, iconPos.y + 2, attributesFrame->getSize().w - 34, iconPos.h - 2 }); | |||
| 13121 | attributeButton->setColor(makeColor(0, 0, 0, 0)); | |||
| 13122 | attributeButton->setHighlightColor(makeColor(0, 0, 0, 0)); | |||
| 13123 | attributeButton->setHideGlyphs(true); | |||
| 13124 | attributeButton->setHideKeyboardGlyphs(true); | |||
| 13125 | attributeButton->setHideSelectors(true); | |||
| 13126 | attributeButton->setMenuConfirmControlType(Widget::MENU_CONFIRM_CONTROLLER); | |||
| 13127 | attributeButton->setTickCallback(charsheet_deselect_fn); | |||
| 13128 | } | |||
| 13129 | } | |||
| 13130 | ||||
| 13131 | { | |||
| 13132 | auto tooltipFrame = sheetFrame->addFrame("sheet tooltip"); | |||
| 13133 | tooltipFrame->setSize(SDL_Rect{ leftAlignX - 200, 0, 200, 200 }); | |||
| 13134 | tooltipFrame->setHollow(true); | |||
| 13135 | tooltipFrame->setInheritParentFrameOpacity(false); | |||
| 13136 | tooltipFrame->setDisabled(true); | |||
| 13137 | Uint32 color = makeColor(255, 255, 255, 255); | |||
| 13138 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13139 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TL_00.png", skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 13140 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13141 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TR_00.png", skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 13142 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13143 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_T_00.png", skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 13144 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13145 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_L_00.png", skillsheetEffectBackgroundImages[MIDDLE_LEFT].c_str()); | |||
| 13146 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13147 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_R_00.png", skillsheetEffectBackgroundImages[MIDDLE_RIGHT].c_str()); | |||
| 13148 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13149 | makeColor(22, 24, 29, 255), "images/system/white.png", skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 13150 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13151 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_BL_00.png", skillsheetEffectBackgroundImages[BOTTOM_LEFT].c_str()); | |||
| 13152 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13153 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_BR_00.png", skillsheetEffectBackgroundImages[BOTTOM_RIGHT].c_str()); | |||
| 13154 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13155 | color, "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_B_00.png", skillsheetEffectBackgroundImages[BOTTOM].c_str()); | |||
| 13156 | imageSetWidthHeight9x9(tooltipFrame, skillsheetEffectBackgroundImages); | |||
| 13157 | imageResizeToContainer9x9(tooltipFrame, SDL_Rect{ 0, 0, 200, 200 }, skillsheetEffectBackgroundImages); | |||
| 13158 | auto txt = tooltipFrame->addField("tooltip text", 1024); | |||
| 13159 | auto txtRightAlignHint = tooltipFrame->addField("tooltip text right align hint", 128); | |||
| 13160 | const char* tooltipFont = "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 13161 | txt->setFont(tooltipFont); | |||
| 13162 | txt->setColor(makeColor(188, 154, 114, 255)); | |||
| 13163 | txtRightAlignHint->setFont(tooltipFont); | |||
| 13164 | txtRightAlignHint->setColor(hudColors.characterSheetFaintText); | |||
| 13165 | auto glyph1 = tooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "images/system/white.png", "glyph 1"); | |||
| 13166 | glyph1->disabled = true; | |||
| 13167 | auto glyph2 = tooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "images/system/white.png", "glyph 2"); | |||
| 13168 | glyph2->disabled = true; | |||
| 13169 | auto glyph3 = tooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "images/system/white.png", "glyph 3"); | |||
| 13170 | glyph3->disabled = true; | |||
| 13171 | auto glyph4 = tooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "images/system/white.png", "glyph 4"); | |||
| 13172 | glyph4->disabled = true; | |||
| 13173 | ||||
| 13174 | for ( int i = 1; i <= NUM_CHARSHEET_TOOLTIP_TEXT_FIELDS; ++i ) | |||
| 13175 | { | |||
| 13176 | char txtEntryFieldName[64] = ""; | |||
| 13177 | snprintf(txtEntryFieldName, sizeof(txtEntryFieldName), "txt %d", i); | |||
| 13178 | auto txtEntry = tooltipFrame->addField(txtEntryFieldName, 1024); | |||
| 13179 | txtEntry->setFont(tooltipFont); | |||
| 13180 | txtEntry->setDisabled(true); | |||
| 13181 | txtEntry->setVJustify(Field::justify_t::CENTER); | |||
| 13182 | txtEntry->setColor(makeColor(188, 154, 114, 255)); | |||
| 13183 | txtEntry->setOntop(true); | |||
| 13184 | ||||
| 13185 | characterSheetTooltipTextFields[player.playernum][i] = txtEntry; | |||
| 13186 | } | |||
| 13187 | ||||
| 13188 | auto div = tooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 1 }, | |||
| 13189 | makeColor(49, 53, 61, 255), | |||
| 13190 | "images/system/white.png", "tooltip divider 1"); | |||
| 13191 | div->disabled = true; | |||
| 13192 | div = tooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 1 }, | |||
| 13193 | makeColor(49, 53, 61, 255), | |||
| 13194 | "images/system/white.png", "tooltip divider 2"); | |||
| 13195 | div->disabled = true; | |||
| 13196 | ||||
| 13197 | ||||
| 13198 | for ( int i = 1; i <= NUM_CHARSHEET_TOOLTIP_BACKING_FRAMES; ++i ) | |||
| 13199 | { | |||
| 13200 | char backingFrameName[64] = ""; | |||
| 13201 | snprintf(backingFrameName, sizeof(backingFrameName), "txt value backing frame %d", i); | |||
| 13202 | auto txtValueBackingFrame = tooltipFrame->addFrame(backingFrameName); | |||
| 13203 | txtValueBackingFrame->setSize(SDL_Rect{ 0, 0, tooltipFrame->getSize().w, tooltipFrame->getSize().h }); | |||
| 13204 | txtValueBackingFrame->setDisabled(true); | |||
| 13205 | Uint32 color = makeColor(51, 33, 26, 255); | |||
| 13206 | txtValueBackingFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13207 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_TL00.png", skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 13208 | txtValueBackingFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13209 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_TR00.png", skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 13210 | txtValueBackingFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13211 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_T00.png", skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 13212 | txtValueBackingFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13213 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_L00.png", skillsheetEffectBackgroundImages[MIDDLE_LEFT].c_str()); | |||
| 13214 | txtValueBackingFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13215 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_R00.png", skillsheetEffectBackgroundImages[MIDDLE_RIGHT].c_str()); | |||
| 13216 | txtValueBackingFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13217 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_M00.png", skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 13218 | txtValueBackingFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13219 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_BL00.png", skillsheetEffectBackgroundImages[BOTTOM_LEFT].c_str()); | |||
| 13220 | txtValueBackingFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13221 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_BR00.png", skillsheetEffectBackgroundImages[BOTTOM_RIGHT].c_str()); | |||
| 13222 | txtValueBackingFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 13223 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_B00.png", skillsheetEffectBackgroundImages[BOTTOM].c_str()); | |||
| 13224 | imageSetWidthHeight9x9(txtValueBackingFrame, skillsheetEffectBackgroundImages); | |||
| 13225 | ||||
| 13226 | characterSheetTooltipTextBackingFrames[player.playernum][i] = txtValueBackingFrame; | |||
| 13227 | } | |||
| 13228 | ||||
| 13229 | { | |||
| 13230 | auto raceTooltip = tooltipFrame->addFrame("sheet race tooltip"); | |||
| 13231 | raceTooltip->setSize(SDL_Rect{ 0, 24, 324, 664 }); | |||
| 13232 | raceTooltip->setDisabled(true); | |||
| 13233 | raceTooltip->setHollow(true); | |||
| 13234 | const auto font = smallfont_outline; | |||
| 13235 | ||||
| 13236 | auto details_text = raceTooltip->addField("details", 1024); | |||
| 13237 | details_text->setFont(font); | |||
| 13238 | details_text->setSize(SDL_Rect{ 0, 0, 242, 300 }); | |||
| 13239 | details_text->setColor(hudColors.characterSheetOffWhiteText); | |||
| 13240 | ||||
| 13241 | auto details_text_right = raceTooltip->addField("details_right", 1024); | |||
| 13242 | details_text_right->setFont(font); | |||
| 13243 | details_text_right->setSize(SDL_Rect{ 121, 0, 121, 300 }); | |||
| 13244 | details_text_right->setColor(hudColors.characterSheetOffWhiteText); | |||
| 13245 | ||||
| 13246 | MainMenu::RaceDescriptions::update_details_text(*raceTooltip, stats[player.playernum]); | |||
| 13247 | } | |||
| 13248 | ||||
| 13249 | { | |||
| 13250 | auto classTooltip = tooltipFrame->addFrame("sheet class tooltip"); | |||
| 13251 | classTooltip->setDisabled(true); | |||
| 13252 | classTooltip->setHollow(true); | |||
| 13253 | auto statGrowths = classTooltip->addFrame("stat growths"); | |||
| 13254 | // stats definitions | |||
| 13255 | const char* class_stats_text[] = { | |||
| 13256 | ItemTooltips.getItemStatShortName("STR").c_str(), | |||
| 13257 | ItemTooltips.getItemStatShortName("DEX").c_str(), | |||
| 13258 | ItemTooltips.getItemStatShortName("CON").c_str(), | |||
| 13259 | ItemTooltips.getItemStatShortName("INT").c_str(), | |||
| 13260 | ItemTooltips.getItemStatShortName("PER").c_str(), | |||
| 13261 | ItemTooltips.getItemStatShortName("CHR").c_str() | |||
| 13262 | }; | |||
| 13263 | constexpr int num_class_stats = sizeof(class_stats_text) / sizeof(class_stats_text[0]); | |||
| 13264 | constexpr SDL_Rect bottom{ 0, 0, 236, 30 }; | |||
| 13265 | constexpr int column = bottom.w / num_class_stats; | |||
| 13266 | ||||
| 13267 | classTooltip->setSize(SDL_Rect{ 0, 0, bottom.w, bottom.h }); | |||
| 13268 | statGrowths->setSize(bottom); | |||
| 13269 | ||||
| 13270 | for ( int c = 0; c < num_class_stats; ++c ) | |||
| 13271 | { | |||
| 13272 | char buf[16]; | |||
| 13273 | snprintf(buf, sizeof(buf), "%d", c); | |||
| 13274 | auto class_stat = statGrowths->addField(buf, 16); | |||
| 13275 | class_stat->setSize(SDL_Rect{ | |||
| 13276 | bottom.x + column * c, bottom.y, column, bottom.h }); | |||
| 13277 | class_stat->setHJustify(Field::justify_t::CENTER); | |||
| 13278 | class_stat->setVJustify(Field::justify_t::TOP); | |||
| 13279 | class_stat->setFont(smallfont_outline); | |||
| 13280 | class_stat->setText(class_stats_text[c]); | |||
| 13281 | //class_stat->setTickCallback([](Widget& widget) {class_stat_fn(*static_cast<Field*>(&widget), widget.getOwner()); }); | |||
| 13282 | ||||
| 13283 | SDL_Rect imgPos = class_stat->getSize(); | |||
| 13284 | imgPos.x += imgPos.w / 2; | |||
| 13285 | imgPos.w = 14; | |||
| 13286 | imgPos.x -= imgPos.w / 2; | |||
| 13287 | imgPos.h = 16; | |||
| 13288 | imgPos.y -= imgPos.h - 4; | |||
| 13289 | ||||
| 13290 | char buf2[32]; | |||
| 13291 | /*snprintf(buf2, sizeof(buf2), "stat img top %d", c); | |||
| 13292 | auto class_stat_img_top = statGrowths->addImage(imgPos, 0xFFFFFFFF, | |||
| 13293 | "*#images/ui/Main Menus/Play/PlayerCreation/ClassSelection/statgrowth_hi2.png", buf2); | |||
| 13294 | class_stat_img_top->disabled = true;*/ | |||
| 13295 | snprintf(buf2, sizeof(buf2), "stat img bottom %d", c); | |||
| 13296 | imgPos.y = class_stat->getSize().y + 17; | |||
| 13297 | auto class_stat_img_bottom = statGrowths->addImage(imgPos, 0xFFFFFFFF, | |||
| 13298 | "*#images/ui/Main Menus/Play/PlayerCreation/ClassSelection/statgrowth_lo2.png", buf2); | |||
| 13299 | class_stat_img_bottom->disabled = true; | |||
| 13300 | } | |||
| 13301 | } | |||
| 13302 | } | |||
| 13303 | } | |||
| 13304 | } | |||
| 13305 | ||||
| 13306 | void Player::GUIDropdown_t::activateSelection(const std::string& name, const int option) | |||
| 13307 | { | |||
| 13308 | auto& dropdown = allDropDowns[name]; | |||
| 13309 | if ( dropdown.options[option].action == "no_action" ) | |||
| 13310 | { | |||
| 13311 | messagePlayer(player.playernum, MESSAGE_DEBUG, "[Dropdowns]: Warning, no action for %s : option %d", name.c_str(), option); | |||
| 13312 | } | |||
| 13313 | else | |||
| 13314 | { | |||
| 13315 | if ( dropdown.options[option].action == "gold_drop_10" ) | |||
| 13316 | { | |||
| 13317 | char dropCommand[32] = ""; | |||
| 13318 | snprintf(dropCommand, sizeof(dropCommand), "/dropgold %d %d", player.playernum, 10); | |||
| 13319 | consoleCommand(dropCommand); | |||
| 13320 | } | |||
| 13321 | else if ( dropdown.options[option].action == "gold_drop_100" ) | |||
| 13322 | { | |||
| 13323 | char dropCommand[32] = ""; | |||
| 13324 | snprintf(dropCommand, sizeof(dropCommand), "/dropgold %d %d", player.playernum, 100); | |||
| 13325 | consoleCommand(dropCommand); | |||
| 13326 | } | |||
| 13327 | else if ( dropdown.options[option].action == "gold_drop_1000" ) | |||
| 13328 | { | |||
| 13329 | char dropCommand[32] = ""; | |||
| 13330 | snprintf(dropCommand, sizeof(dropCommand), "/dropgold %d %d", player.playernum, 1000); | |||
| 13331 | consoleCommand(dropCommand); | |||
| 13332 | } | |||
| 13333 | else if ( dropdown.options[option].action == "gold_drop_all" ) | |||
| 13334 | { | |||
| 13335 | char dropCommand[32] = ""; | |||
| 13336 | snprintf(dropCommand, sizeof(dropCommand), "/dropgold %d %d", player.playernum, std::max(0, stats[player.playernum]->GOLD)); | |||
| 13337 | consoleCommand(dropCommand); | |||
| 13338 | } | |||
| 13339 | else if ( dropdown.options[option].action == "view_status_effects" ) | |||
| 13340 | { | |||
| 13341 | if ( /*StatusEffectQueue[player.playernum].effectQueue.size() > 0*/ true ) | |||
| 13342 | { | |||
| 13343 | player.GUI.previousModule = players[player.playernum]->GUI.activeModule; | |||
| 13344 | if ( !inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 13345 | { | |||
| 13346 | player.GUI.activateModule(Player::GUI_t::MODULE_STATUS_EFFECTS); | |||
| 13347 | } | |||
| 13348 | else | |||
| 13349 | { | |||
| 13350 | player.GUI.activateModule(Player::GUI_t::MODULE_NONE); | |||
| 13351 | } | |||
| 13352 | StatusEffectQueue[player.playernum].selectedElement = 0; | |||
| 13353 | player.hud.statusFxFocusedWindowActive = true; | |||
| 13354 | } | |||
| 13355 | } | |||
| 13356 | else if ( dropdown.options[option].action == "view_portrait" ) | |||
| 13357 | { | |||
| 13358 | if ( playerInventoryFrames[player.playernum].characterPreview ) | |||
| 13359 | { | |||
| 13360 | player.GUI.previousModule = players[player.playernum]->GUI.activeModule; | |||
| 13361 | player.GUI.activateModule(Player::GUI_t::MODULE_PORTRAIT); | |||
| 13362 | ||||
| 13363 | SDL_Rect size = playerInventoryFrames[player.playernum].characterPreview->getAbsoluteSize(); | |||
| 13364 | ||||
| 13365 | // make sure to adjust absolute size to camera viewport | |||
| 13366 | const int offsetX = 4; | |||
| 13367 | const int offsetY = 6; | |||
| 13368 | size.x += offsetX; | |||
| 13369 | size.y += offsetY; | |||
| 13370 | size.w -= offsetX * 2; | |||
| 13371 | size.h -= offsetY * 2; | |||
| 13372 | size.x -= player.camera_virtualx1(); | |||
| 13373 | size.y -= player.camera_virtualy1(); | |||
| 13374 | ||||
| 13375 | player.hud.updateCursorAnimation(size.x - 1, size.y - 1, | |||
| 13376 | size.w, size.h, inputs.getVirtualMouse(player.playernum)->draw_cursor); | |||
| 13377 | player.paperDoll.portraitActiveToEdit = true; | |||
| 13378 | } | |||
| 13379 | } | |||
| 13380 | else if ( dropdown.options[option].action == "inventory_autosort" ) | |||
| 13381 | { | |||
| 13382 | autosortInventory(player.playernum); | |||
| 13383 | //quickStackItems(); | |||
| 13384 | //playSound(139, 64); | |||
| 13385 | } | |||
| 13386 | messagePlayer(player.playernum, MESSAGE_DEBUG, "[Dropdowns]: Executing action '%s' for [%s] : option %d", | |||
| 13387 | dropdown.options[option].action.c_str(), name.c_str(), option); | |||
| 13388 | } | |||
| 13389 | } | |||
| 13390 | ||||
| 13391 | bool Player::GUIDropdown_t::getDropDownAlignRight(const std::string& name) | |||
| 13392 | { | |||
| 13393 | bool invert = false; | |||
| 13394 | if ( name == "drop_gold" ) | |||
| 13395 | { | |||
| 13396 | if ( player.characterSheet.panelJustify == Player::PANEL_JUSTIFY_RIGHT | |||
| 13397 | && (player.bUseCompactGUIHeight() || player.bUseCompactGUIWidth()) ) | |||
| 13398 | { | |||
| 13399 | invert = true; | |||
| 13400 | } | |||
| 13401 | } | |||
| 13402 | else if ( name == "chest_interact" ) | |||
| 13403 | { | |||
| 13404 | if ( player.inventoryUI.bCompactView ) | |||
| 13405 | { | |||
| 13406 | if ( player.inventoryUI.inventoryPanelJustify != PanelJustify_t::PANEL_JUSTIFY_RIGHT ) | |||
| 13407 | { | |||
| 13408 | invert = true; | |||
| 13409 | } | |||
| 13410 | } | |||
| 13411 | } | |||
| 13412 | else if ( name == "paper_doll" ) | |||
| 13413 | { | |||
| 13414 | if ( player.inventoryUI.bCompactView ) | |||
| 13415 | { | |||
| 13416 | if ( player.inventoryUI.paperDollPanelJustify == PanelJustify_t::PANEL_JUSTIFY_RIGHT ) | |||
| 13417 | { | |||
| 13418 | invert = true; | |||
| 13419 | } | |||
| 13420 | } | |||
| 13421 | } | |||
| 13422 | else if ( name == "item_interact" || name == "spell_interact" ) | |||
| 13423 | { | |||
| 13424 | if ( player.inventoryUI.bCompactView ) | |||
| 13425 | { | |||
| 13426 | Item* item = uidToItem(dropDownItem); | |||
| 13427 | if ( item && player.paperDoll.isItemOnDoll(*item) ) | |||
| 13428 | { | |||
| 13429 | if ( player.inventoryUI.paperDollPanelJustify == PanelJustify_t::PANEL_JUSTIFY_RIGHT ) | |||
| 13430 | { | |||
| 13431 | invert = true; | |||
| 13432 | } | |||
| 13433 | } | |||
| 13434 | else if ( item && itemCategory(item) == SPELL_CAT ) | |||
| 13435 | { | |||
| 13436 | if ( player.inventoryUI.spellPanel.panelJustify == PanelJustify_t::PANEL_JUSTIFY_RIGHT ) | |||
| 13437 | { | |||
| 13438 | invert = true; | |||
| 13439 | } | |||
| 13440 | } | |||
| 13441 | else | |||
| 13442 | { | |||
| 13443 | // normal inventory items | |||
| 13444 | if ( player.inventoryUI.inventoryPanelJustify == PanelJustify_t::PANEL_JUSTIFY_RIGHT ) | |||
| 13445 | { | |||
| 13446 | invert = true; | |||
| 13447 | } | |||
| 13448 | } | |||
| 13449 | } | |||
| 13450 | } | |||
| 13451 | return (invert ? !allDropDowns[name].alignRight : allDropDowns[name].alignRight); | |||
| 13452 | } | |||
| 13453 | ||||
| 13454 | void Player::CharacterSheet_t::processCharacterSheet() | |||
| 13455 | { | |||
| 13456 | if ( !sheetFrame ) | |||
| 13457 | { | |||
| 13458 | createCharacterSheet(); | |||
| 13459 | } | |||
| 13460 | ||||
| 13461 | sheetFrame->setSize(SDL_Rect{ players[player.playernum]->camera_virtualx1(), | |||
| 13462 | players[player.playernum]->camera_virtualy1(), | |||
| 13463 | players[player.playernum]->camera_virtualWidth(), | |||
| 13464 | players[player.playernum]->camera_virtualHeight() }); | |||
| 13465 | ||||
| 13466 | if ( !stats[player.playernum] || !players[player.playernum]->isLocalPlayer() ) | |||
| 13467 | { | |||
| 13468 | sheetFrame->setDisabled(true); | |||
| 13469 | queuedElement = SHEET_UNSELECTED; | |||
| 13470 | return; | |||
| 13471 | } | |||
| 13472 | ||||
| 13473 | bool bCompactView = false; | |||
| 13474 | if ( (keystatus[SDLK_u] && enableDebugKeys) || player.bUseCompactGUIHeight() || player.bUseCompactGUIWidth() ) | |||
| 13475 | { | |||
| 13476 | bCompactView = true; | |||
| 13477 | } | |||
| 13478 | ||||
| 13479 | bool hideAndExit = false; | |||
| 13480 | if ( nohud || player.shootmode || !(player.gui_mode == GUI_MODE_INVENTORY || player.gui_mode == GUI_MODE_SHOP) ) | |||
| 13481 | { | |||
| 13482 | hideAndExit = true; | |||
| 13483 | } | |||
| 13484 | else if ( bCompactView && player.hud.compactLayoutMode != Player::HUD_t::COMPACT_LAYOUT_CHARSHEET ) | |||
| 13485 | { | |||
| 13486 | hideAndExit = true; | |||
| 13487 | } | |||
| 13488 | ||||
| 13489 | sheetFrame->setDisabled(false); | |||
| 13490 | ||||
| 13491 | if ( bCompactView ) | |||
| 13492 | { | |||
| 13493 | // justify opposite of inventory | |||
| 13494 | panelJustify = (player.inventoryUI.inventoryPanelJustify == Player::PANEL_JUSTIFY_LEFT) | |||
| 13495 | ? Player::PANEL_JUSTIFY_RIGHT : Player::PANEL_JUSTIFY_LEFT; | |||
| 13496 | } | |||
| 13497 | else | |||
| 13498 | { | |||
| 13499 | panelJustify = Player::PANEL_JUSTIFY_RIGHT; | |||
| 13500 | } | |||
| 13501 | ||||
| 13502 | if ( player.inventoryUI.slideOutPercent <= .0001 ) | |||
| 13503 | { | |||
| 13504 | isInteractable = !hideAndExit; | |||
| 13505 | if ( isInteractable && queuedElement != SHEET_UNSELECTED ) | |||
| 13506 | { | |||
| 13507 | const bool updateCursor = true; | |||
| 13508 | const bool usingMouse = false; | |||
| 13509 | selectElement(queuedElement, usingMouse, updateCursor); | |||
| 13510 | queuedElement = SHEET_UNSELECTED; | |||
| 13511 | } | |||
| 13512 | } | |||
| 13513 | else | |||
| 13514 | { | |||
| 13515 | isInteractable = false; | |||
| 13516 | } | |||
| 13517 | ||||
| 13518 | // resize elements for splitscreen | |||
| 13519 | { | |||
| 13520 | auto characterInfoFrame = sheetFrame->findFrame("character info"); | |||
| 13521 | const int bgWidth = 208; | |||
| 13522 | const int leftAlignX = sheetFrame->getSize().w - bgWidth + player.inventoryUI.slideOutPercent * player.inventoryUI.slideOutWidth; | |||
| 13523 | int compactAlignX1 = -player.inventoryUI.slideOutPercent * player.inventoryUI.slideOutWidth; | |||
| 13524 | int compactAlignX2 = sheetFrame->getSize().w + player.inventoryUI.slideOutPercent * player.inventoryUI.slideOutWidth; | |||
| 13525 | auto compactImgBg = sheetFrame->findImage("character info compact img"); | |||
| 13526 | Frame* dungeonFloorFrame = sheetFrame->findFrame("dungeon floor frame"); | |||
| 13527 | Frame* buttonFrame = sheetFrame->findFrame("log map buttons"); | |||
| 13528 | Frame* fullscreenBg = sheetFrame->findFrame("sheet bg fullscreen"); | |||
| 13529 | Frame* timerFrame = sheetFrame->findFrame("game timer"); | |||
| 13530 | Frame* skillsButtonFrame = sheetFrame->findFrame("skills button frame"); | |||
| 13531 | Frame* characterInnerFrame = characterInfoFrame->findFrame("character info inner frame"); | |||
| 13532 | ||||
| 13533 | auto statsFrame = sheetFrame->findFrame("stats"); | |||
| 13534 | auto attributesFrame = sheetFrame->findFrame("attributes"); | |||
| 13535 | ||||
| 13536 | if ( bCompactView ) | |||
| 13537 | { | |||
| 13538 | // compact view | |||
| 13539 | sheetDisplayType = CHARSHEET_DISPLAY_COMPACT; | |||
| 13540 | ||||
| 13541 | compactImgBg->disabled = false; | |||
| 13542 | compactImgBg->pos.x = (panelJustify == PANEL_JUSTIFY_RIGHT ? compactAlignX1 : compactAlignX2 - compactImgBg->pos.w); | |||
| 13543 | compactImgBg->pos.y = 0; | |||
| 13544 | ||||
| 13545 | SDL_Rect pos = characterInfoFrame->getSize(); | |||
| 13546 | pos.x = (panelJustify == PANEL_JUSTIFY_RIGHT ? compactAlignX1 : compactAlignX2 - pos.w); | |||
| 13547 | pos.y = compactImgBg->pos.y + 60; | |||
| 13548 | characterInfoFrame->setSize(pos); | |||
| 13549 | ||||
| 13550 | SDL_Rect dungeonFloorFramePos = dungeonFloorFrame->getSize(); | |||
| 13551 | dungeonFloorFramePos.x = pos.x + (panelJustify == PANEL_JUSTIFY_RIGHT ? 6 : 0); | |||
| 13552 | dungeonFloorFramePos.y = pos.y - 56; | |||
| 13553 | dungeonFloorFrame->setSize(dungeonFloorFramePos); | |||
| 13554 | ||||
| 13555 | SDL_Rect characterInnerFramePos = characterInnerFrame->getSize(); | |||
| 13556 | characterInnerFramePos.x = (panelJustify == PANEL_JUSTIFY_RIGHT ? 6 : 0); | |||
| 13557 | characterInnerFrame->setSize(characterInnerFramePos); | |||
| 13558 | ||||
| 13559 | SDL_Rect buttonFramePos = buttonFrame->getSize(); | |||
| 13560 | buttonFramePos.w = 198; | |||
| 13561 | buttonFramePos.h = 40; | |||
| 13562 | buttonFramePos.x = (panelJustify == PANEL_JUSTIFY_RIGHT ? compactAlignX1 + 8 : compactAlignX2 - buttonFramePos.w - 8); | |||
| 13563 | buttonFramePos.y = compactImgBg->pos.y + compactImgBg->pos.h + 1; | |||
| 13564 | buttonFrame->setSize(buttonFramePos); | |||
| 13565 | ||||
| 13566 | { | |||
| 13567 | SDL_Rect buttonPos{ 0, 1, 98, 38 }; | |||
| 13568 | auto mapBtn = buttonFrame->findButton("map button"); | |||
| 13569 | mapBtn->setText(Language::get(4071)); | |||
| 13570 | mapBtn->setSize(buttonPos); | |||
| 13571 | auto mapSelector = buttonFrame->findFrame("map button selector"); | |||
| 13572 | SDL_Rect mapSelectorPos = buttonPos; | |||
| 13573 | mapSelectorPos.x += 6; | |||
| 13574 | mapSelectorPos.w -= 12; | |||
| 13575 | mapSelectorPos.y += 4; | |||
| 13576 | mapSelectorPos.h -= 8; | |||
| 13577 | mapSelector->setSize(mapSelectorPos); | |||
| 13578 | ||||
| 13579 | buttonPos.x = buttonFramePos.w - buttonPos.w; | |||
| 13580 | auto logBtn = buttonFrame->findButton("log button"); | |||
| 13581 | logBtn->setText(Language::get(4072)); | |||
| 13582 | logBtn->setSize(buttonPos); | |||
| 13583 | auto logSelector = buttonFrame->findFrame("log button selector"); | |||
| 13584 | SDL_Rect logSelectorPos = buttonPos; | |||
| 13585 | logSelectorPos.x += 6; | |||
| 13586 | logSelectorPos.w -= 12; | |||
| 13587 | logSelectorPos.y += 4; | |||
| 13588 | logSelectorPos.h -= 10; | |||
| 13589 | logSelector->setSize(logSelectorPos); | |||
| 13590 | } | |||
| 13591 | ||||
| 13592 | fullscreenBg->setDisabled(true); | |||
| 13593 | ||||
| 13594 | auto statsPos = statsFrame->getSize(); | |||
| 13595 | statsPos.x = (panelJustify == PANEL_JUSTIFY_RIGHT ? compactAlignX2 - statsPos.w : compactAlignX1); | |||
| 13596 | statsPos.y = 0; | |||
| 13597 | statsFrame->setSize(statsPos); | |||
| 13598 | ||||
| 13599 | auto attributesPos = attributesFrame->getSize(); | |||
| 13600 | attributesPos.x = (panelJustify == PANEL_JUSTIFY_RIGHT ? compactAlignX2 - attributesPos.w : compactAlignX1); | |||
| 13601 | attributesPos.y = statsPos.y + statsPos.h - 4; // 4 pixels above bottom edge of stats pane | |||
| 13602 | attributesFrame->setSize(attributesPos); | |||
| 13603 | } | |||
| 13604 | else | |||
| 13605 | { | |||
| 13606 | // standard view | |||
| 13607 | sheetDisplayType = CHARSHEET_DISPLAY_NORMAL; | |||
| 13608 | ||||
| 13609 | SDL_Rect pos = characterInfoFrame->getSize(); | |||
| 13610 | pos.x = leftAlignX; | |||
| 13611 | pos.y = 206; | |||
| 13612 | characterInfoFrame->setSize(pos); | |||
| 13613 | ||||
| 13614 | SDL_Rect dungeonFloorFramePos = dungeonFloorFrame->getSize(); | |||
| 13615 | dungeonFloorFramePos.x = pos.x + 6; | |||
| 13616 | dungeonFloorFramePos.y = pos.y - 88; | |||
| 13617 | dungeonFloorFrame->setSize(dungeonFloorFramePos); | |||
| 13618 | ||||
| 13619 | SDL_Rect characterInnerFramePos = characterInnerFrame->getSize(); | |||
| 13620 | characterInnerFramePos.x = (panelJustify == PANEL_JUSTIFY_RIGHT ? 6 : 0); | |||
| 13621 | characterInnerFrame->setSize(characterInnerFramePos); | |||
| 13622 | ||||
| 13623 | SDL_Rect buttonFramePos = buttonFrame->getSize(); | |||
| 13624 | buttonFramePos.x = leftAlignX + 9; | |||
| 13625 | buttonFramePos.y = 6; | |||
| 13626 | buttonFramePos.w = 196; | |||
| 13627 | buttonFramePos.h = 82; | |||
| 13628 | buttonFrame->setSize(buttonFramePos); | |||
| 13629 | { | |||
| 13630 | SDL_Rect buttonPos{ 0, 0, buttonFramePos.w, 40 }; | |||
| 13631 | auto mapBtn = buttonFrame->findButton("map button"); | |||
| 13632 | mapBtn->setText(Language::get(4069)); | |||
| 13633 | mapBtn->setSize(buttonPos); | |||
| 13634 | auto mapSelector = buttonFrame->findFrame("map button selector"); | |||
| 13635 | mapSelector->setSize(buttonPos); | |||
| 13636 | ||||
| 13637 | buttonPos.y = buttonPos.y + buttonPos.h + 2; | |||
| 13638 | auto logBtn = buttonFrame->findButton("log button"); | |||
| 13639 | logBtn->setText(Language::get(4070)); | |||
| 13640 | logBtn->setSize(buttonPos); | |||
| 13641 | auto logSelector = buttonFrame->findFrame("log button selector"); | |||
| 13642 | logSelector->setSize(buttonPos); | |||
| 13643 | } | |||
| 13644 | ||||
| 13645 | SDL_Rect timerFramePos = timerFrame->getSize(); | |||
| 13646 | timerFramePos.x = leftAlignX + 36; | |||
| 13647 | timerFrame->setSize(timerFramePos); | |||
| 13648 | ||||
| 13649 | SDL_Rect skillsButtonFramePos = skillsButtonFrame->getSize(); | |||
| 13650 | skillsButtonFramePos.x = leftAlignX + 14; | |||
| 13651 | skillsButtonFrame->setSize(skillsButtonFramePos); | |||
| 13652 | ||||
| 13653 | fullscreenBg->setDisabled(false); | |||
| 13654 | SDL_Rect fullscreenBgPos = fullscreenBg->getSize(); | |||
| 13655 | fullscreenBgPos.x = sheetFrame->getSize().w - fullscreenBgPos.w + player.inventoryUI.slideOutPercent * player.inventoryUI.slideOutWidth; | |||
| 13656 | fullscreenBg->setSize(fullscreenBgPos); | |||
| 13657 | compactImgBg->disabled = true; | |||
| 13658 | ||||
| 13659 | Frame::image_t* fullscreenBgImg = fullscreenBg->findImage("bg image"); | |||
| 13660 | ||||
| 13661 | auto statsPos = statsFrame->getSize(); | |||
| 13662 | statsPos.x = sheetFrame->getSize().w - statsPos.w + player.inventoryUI.slideOutPercent * player.inventoryUI.slideOutWidth; | |||
| 13663 | statsPos.y = fullscreenBgImg->pos.y + fullscreenBgImg->pos.h; | |||
| 13664 | statsFrame->setSize(statsPos); | |||
| 13665 | ||||
| 13666 | auto attributesPos = attributesFrame->getSize(); | |||
| 13667 | attributesPos.x = sheetFrame->getSize().w - attributesPos.w + player.inventoryUI.slideOutPercent * player.inventoryUI.slideOutWidth; | |||
| 13668 | attributesPos.y = statsPos.y + statsPos.h - 4; // 4 px overlap attributes pane | |||
| 13669 | attributesFrame->setSize(attributesPos); | |||
| 13670 | ||||
| 13671 | } | |||
| 13672 | } | |||
| 13673 | ||||
| 13674 | updateCharacterSheetTooltip(SHEET_UNSELECTED, SDL_Rect{ 0, 0, 0, 0 }); // to reset the tooltip from displaying. | |||
| 13675 | if ( hideAndExit ) | |||
| 13676 | { | |||
| 13677 | queuedElement = SHEET_UNSELECTED; | |||
| 13678 | sheetFrame->setDisabled(true); | |||
| 13679 | return; | |||
| 13680 | } | |||
| 13681 | ||||
| 13682 | player.GUI.handleCharacterSheetMovement(); | |||
| 13683 | ||||
| 13684 | { | |||
| 13685 | auto characterInfoFrame = sheetFrame->findFrame("character info"); | |||
| 13686 | assert(characterInfoFrame)(static_cast<void> (0)); | |||
| 13687 | auto characterInnerFrame = characterInfoFrame->findFrame("character info inner frame"); | |||
| 13688 | assert(characterInnerFrame)(static_cast<void> (0)); | |||
| 13689 | auto statsFrame = sheetFrame->findFrame("stats"); | |||
| 13690 | assert(statsFrame)(static_cast<void> (0)); | |||
| 13691 | auto statsInnerFrame = statsFrame->findFrame("stats inner frame"); | |||
| 13692 | assert(statsInnerFrame)(static_cast<void> (0)); | |||
| 13693 | auto attributesFrame = sheetFrame->findFrame("attributes"); | |||
| 13694 | assert(attributesFrame)(static_cast<void> (0)); | |||
| 13695 | auto attributesInnerFrame = attributesFrame->findFrame("attributes inner frame"); | |||
| 13696 | assert(attributesInnerFrame)(static_cast<void> (0)); | |||
| 13697 | SheetElements targetElement = SHEET_ENUM_END; | |||
| 13698 | auto logButton = sheetFrame->findFrame("log map buttons")->findButton("log button"); | |||
| 13699 | auto mapButton = sheetFrame->findFrame("log map buttons")->findButton("map button"); | |||
| 13700 | auto skillsButton = sheetFrame->findFrame("skills button frame")->findButton("skills button"); | |||
| 13701 | Button* strButton = statsInnerFrame->findButton("str button"); | |||
| 13702 | Button* dexButton = statsInnerFrame->findButton("dex button"); | |||
| 13703 | Button* conButton = statsInnerFrame->findButton("con button"); | |||
| 13704 | Button* intButton = statsInnerFrame->findButton("int button"); | |||
| 13705 | Button* perButton = statsInnerFrame->findButton("per button"); | |||
| 13706 | Button* chrButton = statsInnerFrame->findButton("chr button"); | |||
| 13707 | Button* atkButton = attributesInnerFrame->findButton("atk button"); | |||
| 13708 | Button* acButton = attributesInnerFrame->findButton("ac button"); | |||
| 13709 | Button* powButton = attributesInnerFrame->findButton("pow button"); | |||
| 13710 | Button* resButton = attributesInnerFrame->findButton("res button"); | |||
| 13711 | Button* rgnButton = attributesInnerFrame->findButton("rgn button"); | |||
| 13712 | Button* rgnMpButton = attributesInnerFrame->findButton("rgn mp button"); | |||
| 13713 | Button* wgtButton = attributesInnerFrame->findButton("wgt button"); | |||
| 13714 | ||||
| 13715 | auto sheetTimer = sheetFrame->findFrame("game timer"); | |||
| 13716 | if ( bCompactView ) | |||
| 13717 | { | |||
| 13718 | sheetTimer->setDisabled(true); | |||
| 13719 | } | |||
| 13720 | else | |||
| 13721 | { | |||
| 13722 | sheetTimer->setDisabled(false); | |||
| 13723 | } | |||
| 13724 | ||||
| 13725 | bool mouseHighlightActive = inputs.getVirtualMouse(player.playernum)->draw_cursor | |||
| 13726 | && (!player.GUI.isDropdownActive()) | |||
| 13727 | && isInteractable; | |||
| 13728 | ||||
| 13729 | if ( player.bUseCompactGUIWidth() | |||
| 13730 | && (player.minimap.mapWindow || player.messageZone.logWindow) ) | |||
| 13731 | { | |||
| 13732 | mouseHighlightActive = false; | |||
| 13733 | } | |||
| 13734 | ||||
| 13735 | if ( mouseHighlightActive ) | |||
| 13736 | { | |||
| 13737 | if ( skillsButton->isHighlighted() ) | |||
| 13738 | { | |||
| 13739 | targetElement = SHEET_SKILL_LIST; | |||
| 13740 | } | |||
| 13741 | else if ( logButton->isHighlighted() ) | |||
| 13742 | { | |||
| 13743 | targetElement = SHEET_OPEN_LOG; | |||
| 13744 | } | |||
| 13745 | else if ( mapButton->isHighlighted() ) | |||
| 13746 | { | |||
| 13747 | targetElement = SHEET_OPEN_MAP; | |||
| 13748 | } | |||
| 13749 | else if ( !sheetTimer->isDisabled() && sheetTimer->findButton("timer selector")->isHighlighted() ) | |||
| 13750 | { | |||
| 13751 | targetElement = SHEET_TIMER; | |||
| 13752 | } | |||
| 13753 | else if ( sheetFrame->findFrame("dungeon floor frame")->findButton("dungeon floor selector")->isHighlighted() ) | |||
| 13754 | { | |||
| 13755 | targetElement = SHEET_DUNGEON_FLOOR; | |||
| 13756 | } | |||
| 13757 | else if ( characterInnerFrame->findButton("character class selector")->isHighlighted() ) | |||
| 13758 | { | |||
| 13759 | targetElement = SHEET_CHAR_CLASS; | |||
| 13760 | } | |||
| 13761 | else if ( characterInnerFrame->findButton("character race selector")->isHighlighted() ) | |||
| 13762 | { | |||
| 13763 | targetElement = SHEET_CHAR_RACE_SEX; | |||
| 13764 | } | |||
| 13765 | else if ( characterInnerFrame->findButton("character gold selector")->isHighlighted() ) | |||
| 13766 | { | |||
| 13767 | targetElement = SHEET_GOLD; | |||
| 13768 | } | |||
| 13769 | else if ( strButton->isHighlighted() ) | |||
| 13770 | { | |||
| 13771 | targetElement = SHEET_STR; | |||
| 13772 | } | |||
| 13773 | else if ( dexButton->isHighlighted() ) | |||
| 13774 | { | |||
| 13775 | targetElement = SHEET_DEX; | |||
| 13776 | } | |||
| 13777 | else if ( conButton->isHighlighted() ) | |||
| 13778 | { | |||
| 13779 | targetElement = SHEET_CON; | |||
| 13780 | } | |||
| 13781 | else if ( intButton->isHighlighted() ) | |||
| 13782 | { | |||
| 13783 | targetElement = SHEET_INT; | |||
| 13784 | } | |||
| 13785 | else if ( perButton->isHighlighted() ) | |||
| 13786 | { | |||
| 13787 | targetElement = SHEET_PER; | |||
| 13788 | } | |||
| 13789 | else if ( chrButton->isHighlighted() ) | |||
| 13790 | { | |||
| 13791 | targetElement = SHEET_CHR; | |||
| 13792 | } | |||
| 13793 | else if ( atkButton->isHighlighted() ) | |||
| 13794 | { | |||
| 13795 | targetElement = SHEET_ATK; | |||
| 13796 | } | |||
| 13797 | else if ( acButton->isHighlighted() ) | |||
| 13798 | { | |||
| 13799 | targetElement = SHEET_AC; | |||
| 13800 | } | |||
| 13801 | else if ( powButton->isHighlighted() ) | |||
| 13802 | { | |||
| 13803 | targetElement = SHEET_POW; | |||
| 13804 | } | |||
| 13805 | else if ( resButton->isHighlighted() ) | |||
| 13806 | { | |||
| 13807 | targetElement = SHEET_RES; | |||
| 13808 | } | |||
| 13809 | else if ( rgnButton->isHighlighted() ) | |||
| 13810 | { | |||
| 13811 | targetElement = SHEET_RGN; | |||
| 13812 | } | |||
| 13813 | else if ( rgnMpButton->isHighlighted() ) | |||
| 13814 | { | |||
| 13815 | targetElement = SHEET_RGN_MP; | |||
| 13816 | } | |||
| 13817 | else if ( wgtButton->isHighlighted() ) | |||
| 13818 | { | |||
| 13819 | targetElement = SHEET_WGT; | |||
| 13820 | } | |||
| 13821 | } | |||
| 13822 | if ( targetElement != SHEET_ENUM_END ) | |||
| 13823 | { | |||
| 13824 | player.GUI.activateModule(Player::GUI_t::MODULE_CHARACTERSHEET); | |||
| 13825 | selectElement(targetElement, true, true); | |||
| 13826 | } | |||
| 13827 | else | |||
| 13828 | { | |||
| 13829 | if ( inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 13830 | { | |||
| 13831 | if ( player.GUI.activeModule == Player::GUI_t::MODULE_CHARACTERSHEET | |||
| 13832 | && !player.GUI.isDropdownActive() && !player.GUI.dropdownMenu.bClosedThisTick ) | |||
| 13833 | { | |||
| 13834 | // no moused over objects, deactivate the cursor. | |||
| 13835 | player.GUI.activateModule(Player::GUI_t::MODULE_NONE); | |||
| 13836 | } | |||
| 13837 | } | |||
| 13838 | } | |||
| 13839 | //messagePlayer(0, "%d", player.GUI.activeModule); | |||
| 13840 | // players[player.playernum]->GUI.warpControllerToModule(false); - use this for controller input | |||
| 13841 | } | |||
| 13842 | ||||
| 13843 | updateGameTimer(); | |||
| 13844 | updateStats(); | |||
| 13845 | updateAttributes(); | |||
| 13846 | updateCharacterInfo(); | |||
| 13847 | } | |||
| 13848 | ||||
| 13849 | std::map<std::string, Player::GUIDropdown_t::DropDown_t> Player::GUIDropdown_t::allDropDowns; | |||
| 13850 | ||||
| 13851 | bool Player::GUIDropdown_t::set(const std::string name) | |||
| 13852 | { | |||
| 13853 | if ( allDropDowns.find(name) == allDropDowns.end() ) | |||
| 13854 | { | |||
| 13855 | printlog("[Dropdown]: Could not find dropdown name %s", name.c_str()); | |||
| 13856 | return false; | |||
| 13857 | } | |||
| 13858 | ||||
| 13859 | if ( currentName != name ) | |||
| 13860 | { | |||
| 13861 | create(name); | |||
| 13862 | } | |||
| 13863 | currentName = name; | |||
| 13864 | return true; | |||
| 13865 | } | |||
| 13866 | ||||
| 13867 | void Player::GUIDropdown_t::process() | |||
| 13868 | { | |||
| 13869 | bClosedThisTick = false; | |||
| 13870 | if ( dropdownBlockClickFrame ) | |||
| ||||
| 13871 | { | |||
| 13872 | dropdownBlockClickFrame->setSize(SDL_Rect{ players[player.playernum]->camera_virtualx1(), | |||
| 13873 | players[player.playernum]->camera_virtualy1(), | |||
| 13874 | players[player.playernum]->camera_virtualWidth(), | |||
| 13875 | players[player.playernum]->camera_virtualHeight() }); | |||
| 13876 | } | |||
| 13877 | if ( !dropdownFrame ) { return; } | |||
| 13878 | ||||
| 13879 | if ( !bOpen ) | |||
| 13880 | { | |||
| 13881 | dropdownFrame->setDisabled(true); | |||
| 13882 | dropDownOptionSelected = -1; | |||
| 13883 | dropDownItem = 0; | |||
| 13884 | dropDownX = 0; | |||
| 13885 | dropDownY = 0; | |||
| 13886 | dropDownToggleClick = false; | |||
| 13887 | return; | |||
| 13888 | } | |||
| 13889 | else | |||
| 13890 | { | |||
| 13891 | dropdownFrame->setDisabled(false); | |||
| 13892 | } | |||
| 13893 | ||||
| 13894 | auto highlightImageMid = dropdownFrame->findImage("interact selected highlight mid"); | |||
| 13895 | highlightImageMid->disabled = true; | |||
| 13896 | highlightImageMid->color = hudColors.itemContextMenuOptionSelectedImg; | |||
| 13897 | auto highlightImageLeft = dropdownFrame->findImage("interact selected highlight left"); | |||
| 13898 | highlightImageLeft->disabled = true; | |||
| 13899 | highlightImageLeft->color = hudColors.itemContextMenuOptionSelectedImg; | |||
| 13900 | auto highlightImageRight = dropdownFrame->findImage("interact selected highlight right"); | |||
| 13901 | highlightImageRight->disabled = true; | |||
| 13902 | highlightImageRight->color = hudColors.itemContextMenuOptionSelectedImg; | |||
| 13903 | ||||
| 13904 | size_t index = 0; | |||
| 13905 | unsigned int maxWidth = 0; | |||
| 13906 | if ( auto interactText = dropdownFrame->findField("interact text") ) | |||
| 13907 | { | |||
| 13908 | interactText->setColor(hudColors.itemContextMenuHeadingText); | |||
| 13909 | if ( auto textGet = Text::get(interactText->getText(), interactText->getFont(), | |||
| 13910 | interactText->getTextColor(), interactText->getOutlineColor()) ) | |||
| 13911 | { | |||
| 13912 | maxWidth = textGet->getWidth(); | |||
| 13913 | } | |||
| 13914 | } | |||
| 13915 | int maxHeight = 0; | |||
| 13916 | const int textPaddingX = 8; | |||
| 13917 | ||||
| 13918 | auto dropDown = allDropDowns[currentName]; | |||
| 13919 | std::vector<ItemContextMenuPrompts> contextOptions; | |||
| 13920 | Item* item = uidToItem(dropDownItem); | |||
| 13921 | if ( currentName == "chest_interact" ) | |||
| 13922 | { | |||
| 13923 | list_t* chest_inventory = nullptr; | |||
| 13924 | if ( openedChest[player.playernum] ) | |||
| 13925 | { | |||
| 13926 | if ( multiplayer == CLIENT2 ) | |||
| 13927 | { | |||
| 13928 | chest_inventory = &chestInv[player.playernum]; | |||
| 13929 | } | |||
| 13930 | else if ( openedChest[player.playernum]->children.first && openedChest[player.playernum]->children.first->element ) | |||
| 13931 | { | |||
| 13932 | chest_inventory = (list_t*)openedChest[player.playernum]->children.first->element; | |||
| 13933 | } | |||
| 13934 | } | |||
| 13935 | ||||
| 13936 | if ( chest_inventory ) | |||
| 13937 | { | |||
| 13938 | for ( node_t* node = chest_inventory->first; node != NULL__null; node = node->next ) | |||
| 13939 | { | |||
| 13940 | Item* chestItem = (Item*)node->element; | |||
| 13941 | if ( !chestItem ) | |||
| 13942 | { | |||
| 13943 | continue; | |||
| 13944 | } | |||
| 13945 | if ( chestItem->uid == dropDownItem ) | |||
| 13946 | { | |||
| 13947 | item = chestItem; | |||
| 13948 | break; | |||
| 13949 | } | |||
| 13950 | } | |||
| 13951 | } | |||
| 13952 | } | |||
| 13953 | ||||
| 13954 | if ( dropDownItem != 0 && !item ) | |||
| 13955 | { | |||
| 13956 | close(); | |||
| 13957 | return; | |||
| 13958 | } | |||
| 13959 | if ( currentName == "item_interact" || currentName == "hotbar_interact" | |||
| 13960 | || currentName == "chest_interact" | |||
| 13961 | || currentName == "spell_interact" ) | |||
| 13962 | { | |||
| 13963 | if ( item ) | |||
| 13964 | { | |||
| 13965 | dropDown.options.clear(); | |||
| 13966 | contextOptions = getContextMenuOptionsForItem(player.playernum, item); | |||
| 13967 | if ( currentName == "hotbar_interact" ) | |||
| 13968 | { | |||
| 13969 | contextOptions.push_back(PROMPT_CLEAR_HOTBAR_SLOT); | |||
| 13970 | if ( itemCategory(item) == SPELLBOOK ) | |||
| 13971 | { | |||
| 13972 | for ( auto it = contextOptions.begin(); it != contextOptions.end(); ++it ) | |||
| 13973 | { | |||
| 13974 | if ( (*it) == PROMPT_INTERACT ) | |||
| 13975 | { | |||
| 13976 | (*it) = PROMPT_INTERACT_SPELLBOOK_HOTBAR; | |||
| 13977 | } | |||
| 13978 | } | |||
| 13979 | } | |||
| 13980 | } | |||
| 13981 | if ( player.inventoryUI.useItemDropdownOnGamepad == Inventory_t::GAMEPAD_DROPDOWN_FULL ) | |||
| 13982 | { | |||
| 13983 | for ( auto it = contextOptions.begin(); it != contextOptions.end(); ) | |||
| 13984 | { | |||
| 13985 | if ( (*it) == PROMPT_APPRAISE ) | |||
| 13986 | { | |||
| 13987 | it = contextOptions.erase(it); | |||
| 13988 | continue; | |||
| 13989 | } | |||
| 13990 | ++it; | |||
| 13991 | } | |||
| 13992 | } | |||
| 13993 | else if ( player.inventoryUI.useItemDropdownOnGamepad == Inventory_t::GAMEPAD_DROPDOWN_COMPACT ) | |||
| 13994 | { | |||
| 13995 | for ( auto it = contextOptions.begin(); it != contextOptions.end(); ) | |||
| 13996 | { | |||
| 13997 | if ( (*it) == PROMPT_APPRAISE || (*it) == PROMPT_DROP ) | |||
| 13998 | { | |||
| 13999 | it = contextOptions.erase(it); | |||
| 14000 | continue; | |||
| 14001 | } | |||
| 14002 | ++it; | |||
| 14003 | } | |||
| 14004 | } | |||
| 14005 | for ( auto option : contextOptions ) | |||
| 14006 | { | |||
| 14007 | dropDown.options.push_back(DropdownOption_t(getContextMenuLangEntry(player.playernum, option, *item), "", "", "")); | |||
| 14008 | } | |||
| 14009 | } | |||
| 14010 | } | |||
| 14011 | if ( dropDown.module != Player::GUI_t::MODULE_NONE ) | |||
| 14012 | { | |||
| 14013 | if ( dropDown.module != player.GUI.activeModule ) | |||
| 14014 | { | |||
| 14015 | close(); | |||
| 14016 | return; | |||
| 14017 | } | |||
| 14018 | } | |||
| 14019 | ||||
| 14020 | if ( !inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 14021 | { | |||
| 14022 | bool pressedDown = Input::inputs[player.playernum].consumeBinaryToggle("InventoryMoveDown"); | |||
| 14023 | pressedDown = Input::inputs[player.playernum].consumeBinaryToggle("InventoryMoveDownAnalog") || pressedDown; | |||
| 14024 | ||||
| 14025 | bool pressedUp = Input::inputs[player.playernum].consumeBinaryToggle("InventoryMoveUp"); | |||
| 14026 | pressedUp = Input::inputs[player.playernum].consumeBinaryToggle("InventoryMoveUpAnalog") || pressedUp; | |||
| 14027 | ||||
| 14028 | if ( pressedDown && player.bControlEnabled && !gamePaused && !player.usingCommand() ) | |||
| 14029 | { | |||
| 14030 | ++dropDownOptionSelected; | |||
| 14031 | if ( dropDownOptionSelected >= dropDown.options.size() ) | |||
| 14032 | { | |||
| 14033 | dropDownOptionSelected = 0; | |||
| 14034 | } | |||
| 14035 | Player::soundMovement(); | |||
| 14036 | } | |||
| 14037 | else if ( pressedUp && player.bControlEnabled && !gamePaused && !player.usingCommand() ) | |||
| 14038 | { | |||
| 14039 | --dropDownOptionSelected; | |||
| 14040 | if ( dropDownOptionSelected < 0 ) | |||
| 14041 | { | |||
| 14042 | dropDownOptionSelected = dropDown.options.size() - 1; | |||
| 14043 | } | |||
| 14044 | Player::soundMovement(); | |||
| 14045 | } | |||
| 14046 | } | |||
| 14047 | ||||
| 14048 | std::vector<std::tuple<Frame::image_t*, Field*, Frame::image_t*>> optionFrames; | |||
| 14049 | index = 1; | |||
| 14050 | for ( auto& option : dropDown.options ) | |||
| 14051 | { | |||
| 14052 | char glyphname[32] = ""; | |||
| 14053 | snprintf(glyphname, sizeof(glyphname), "glyph %d", (int)index); | |||
| 14054 | char optionname[32] = ""; | |||
| 14055 | snprintf(optionname, sizeof(optionname), "interact option %d", (int)index); | |||
| 14056 | ||||
| 14057 | auto img = dropdownFrame->findImage(glyphname); | |||
| 14058 | auto txt = dropdownFrame->findField(optionname); | |||
| 14059 | optionFrames.push_back(std::make_tuple(img, txt, nullptr)); | |||
| 14060 | txt->setColor(hudColors.itemContextMenuOptionText); | |||
| 14061 | //txt->setColor(makeColor(148, 82, 3, 255)); | |||
| 14062 | txt->setDisabled(false); | |||
| 14063 | img->disabled = true; | |||
| 14064 | ||||
| 14065 | if ( !inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 14066 | { | |||
| 14067 | if ( dropDownOptionSelected + 1 == index ) | |||
| 14068 | { | |||
| 14069 | img->path = Input::inputs[player.playernum].getGlyphPathForBinding("MenuConfirm"); | |||
| 14070 | if ( auto imgGet = Image::get(img->path.c_str()) ) | |||
| 14071 | { | |||
| 14072 | img->pos.w = imgGet->getWidth(); | |||
| 14073 | img->pos.h = imgGet->getHeight(); | |||
| 14074 | img->disabled = false; | |||
| 14075 | } | |||
| 14076 | } | |||
| 14077 | } | |||
| 14078 | /*if ( option.controllerGlyph != "" && inputs.getVirtualMouse(player.playernum)->lastMovementFromController ) | |||
| 14079 | { | |||
| 14080 | img->path = Input::inputs[player.playernum].getGlyphPathForBinding(option.controllerGlyph.c_str()); | |||
| 14081 | img->disabled = false; | |||
| 14082 | } | |||
| 14083 | else if ( option.keyboardGlyph != "" && inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 14084 | { | |||
| 14085 | img->path = Input::inputs[player.playernum].getGlyphPathForBinding(option.keyboardGlyph.c_str()); | |||
| 14086 | img->disabled = false; | |||
| 14087 | }*/ | |||
| 14088 | ||||
| 14089 | txt->setText(option.text.c_str()); | |||
| 14090 | if ( auto textGet = Text::get(txt->getText(), txt->getFont(), | |||
| 14091 | txt->getTextColor(), txt->getOutlineColor()) ) | |||
| 14092 | { | |||
| 14093 | maxWidth = std::max(textGet->getWidth() + 40, maxWidth); | |||
| 14094 | ||||
| 14095 | SDL_Rect size = txt->getSize(); | |||
| 14096 | size.w = textGet->getWidth(); | |||
| 14097 | if ( img->disabled || true ) | |||
| 14098 | { | |||
| 14099 | size.x = textPaddingX; | |||
| 14100 | txt->setHJustify(Field::justify_t::CENTER); | |||
| 14101 | } | |||
| 14102 | else | |||
| 14103 | { | |||
| 14104 | size.x = img->pos.x + img->pos.w + textPaddingX; | |||
| 14105 | txt->setHJustify(Field::justify_t::LEFT); | |||
| 14106 | } | |||
| 14107 | txt->setSize(size); | |||
| 14108 | } | |||
| 14109 | ||||
| 14110 | img->pos.x = txt->getSize().x - 8; | |||
| 14111 | img->pos.y = txt->getSize().y + txt->getSize().h / 2 - img->pos.h / 2; | |||
| 14112 | ||||
| 14113 | maxHeight = std::max(std::max(txt->getSize().y + txt->getSize().h, img->pos.y + img->pos.h), maxHeight); | |||
| 14114 | ++index; | |||
| 14115 | } | |||
| 14116 | ||||
| 14117 | const int rightClickProtectBuffer = (right_click_protect ? 0 : 10); | |||
| 14118 | const Sint32 mousex = (inputs.getMouse(player.playernum, Inputs::X) / (float)xres) * (float)Frame::virtualScreenX; | |||
| 14119 | const Sint32 mousey = (inputs.getMouse(player.playernum, Inputs::Y) / (float)yres) * (float)Frame::virtualScreenY; | |||
| 14120 | ||||
| 14121 | index = 0; | |||
| 14122 | bool alignRight = getDropDownAlignRight(currentName); | |||
| 14123 | for ( auto& optionGlyphTextBacking : optionFrames ) | |||
| 14124 | { | |||
| 14125 | auto img = std::get<0>(optionGlyphTextBacking); | |||
| 14126 | auto txt = std::get<1>(optionGlyphTextBacking); | |||
| 14127 | ||||
| 14128 | if ( txt->getHJustify() == Field::justify_t::CENTER || true ) | |||
| 14129 | { | |||
| 14130 | SDL_Rect size = txt->getSize(); | |||
| 14131 | size.w = maxWidth; | |||
| 14132 | txt->setSize(size); | |||
| 14133 | } | |||
| 14134 | ||||
| 14135 | if ( inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 14136 | { | |||
| 14137 | auto ml = dropdownFrame->findImage("interact middle left"); | |||
| 14138 | SDL_Rect absoluteSize = txt->getAbsoluteSize(); | |||
| 14139 | absoluteSize.x -= (4 + ml->pos.w) + (alignRight ? rightClickProtectBuffer : 0); | |||
| 14140 | absoluteSize.w += ((4 + ml->pos.w) * 2 + rightClickProtectBuffer); | |||
| 14141 | absoluteSize.y += 4; | |||
| 14142 | absoluteSize.h -= 4; | |||
| 14143 | if ( mousex >= absoluteSize.x && mousex < absoluteSize.x + absoluteSize.w | |||
| 14144 | && mousey >= absoluteSize.y && mousey < absoluteSize.y + absoluteSize.h ) | |||
| 14145 | { | |||
| 14146 | dropDownOptionSelected = index; | |||
| 14147 | } | |||
| 14148 | } | |||
| 14149 | ++index; | |||
| 14150 | } | |||
| 14151 | ||||
| 14152 | int textStartX = textPaddingX; | |||
| 14153 | //if ( optionFrames.size() > 0 ) | |||
| 14154 | //{ | |||
| 14155 | // auto img = std::get<0>(optionFrames[0]); | |||
| 14156 | // textStartX += (img->disabled ? 0 : img->pos.x + img->pos.w); | |||
| 14157 | //} | |||
| 14158 | const int frameWidth = maxWidth + textStartX + textPaddingX; | |||
| 14159 | ||||
| 14160 | SDL_Rect frameSize = dropdownFrame->getSize(); | |||
| 14161 | frameSize.x = dropDownX; | |||
| 14162 | frameSize.y = dropDownY; | |||
| 14163 | ||||
| 14164 | // position the frame elements | |||
| 14165 | int interimHeight = 0; | |||
| 14166 | { | |||
| 14167 | auto tl = dropdownFrame->findImage("interact top left"); | |||
| 14168 | auto tmid = dropdownFrame->findImage("interact top background"); | |||
| 14169 | tmid->pos.w = frameWidth - tl->pos.w * 2; | |||
| 14170 | auto tr = dropdownFrame->findImage("interact top right"); | |||
| 14171 | tr->pos.x = tmid->pos.x + tmid->pos.w; | |||
| 14172 | ||||
| 14173 | interimHeight = tmid->pos.y + tmid->pos.h; | |||
| 14174 | frameSize.w = tr->pos.x + tr->pos.w; | |||
| 14175 | } | |||
| 14176 | { | |||
| 14177 | const int middleOffsetY = 13; | |||
| 14178 | auto ml = dropdownFrame->findImage("interact middle left"); | |||
| 14179 | ml->pos.h = maxHeight - interimHeight - middleOffsetY; | |||
| 14180 | auto mmid = dropdownFrame->findImage("interact middle background"); | |||
| 14181 | mmid->pos.h = ml->pos.h; | |||
| 14182 | mmid->pos.w = frameWidth - (ml->pos.w) * 2; | |||
| 14183 | mmid->color = hudColors.itemContextMenuOptionImg; | |||
| 14184 | auto mr = dropdownFrame->findImage("interact middle right"); | |||
| 14185 | mr->pos.h = ml->pos.h; | |||
| 14186 | mr->pos.x = mmid->pos.x + mmid->pos.w; | |||
| 14187 | ||||
| 14188 | interimHeight = mmid->pos.y + mmid->pos.h; | |||
| 14189 | } | |||
| 14190 | { | |||
| 14191 | auto bl = dropdownFrame->findImage("interact bottom left"); | |||
| 14192 | bl->pos.y = interimHeight; | |||
| 14193 | auto bmid = dropdownFrame->findImage("interact bottom background"); | |||
| 14194 | bmid->pos.y = interimHeight; | |||
| 14195 | bmid->pos.w = frameWidth - bl->pos.w * 2; | |||
| 14196 | auto br = dropdownFrame->findImage("interact bottom right"); | |||
| 14197 | br->pos.y = interimHeight; | |||
| 14198 | br->pos.x = bmid->pos.x + bmid->pos.w; | |||
| 14199 | ||||
| 14200 | frameSize.h = br->pos.y + br->pos.h; | |||
| 14201 | } | |||
| 14202 | ||||
| 14203 | if ( auto interactText = dropdownFrame->findField("interact text") ) | |||
| 14204 | { | |||
| 14205 | SDL_Rect size = interactText->getSize(); | |||
| 14206 | size.x = 0; | |||
| 14207 | size.w = frameSize.w; | |||
| 14208 | interactText->setSize(size); | |||
| 14209 | } | |||
| 14210 | ||||
| 14211 | if ( !alignRight ) | |||
| 14212 | { | |||
| 14213 | frameSize.x -= frameSize.w; | |||
| 14214 | } | |||
| 14215 | if ( frameSize.y + frameSize.h > player.camera_virtualy2() ) | |||
| 14216 | { | |||
| 14217 | frameSize.y -= (frameSize.y + frameSize.h) - player.camera_virtualy2(); | |||
| 14218 | } | |||
| 14219 | dropdownFrame->setSize(frameSize); | |||
| 14220 | ||||
| 14221 | if ( inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 14222 | { | |||
| 14223 | SDL_Rect absoluteSize = dropdownFrame->getAbsoluteSize(); | |||
| 14224 | // right click protect uses exact border, else there is 10 px buffer | |||
| 14225 | absoluteSize.x -= (alignRight ? rightClickProtectBuffer : 0); | |||
| 14226 | absoluteSize.w += rightClickProtectBuffer; | |||
| 14227 | if ( !(mousex >= absoluteSize.x && mousex < absoluteSize.x + absoluteSize.w | |||
| 14228 | && mousey >= absoluteSize.y && mousey < absoluteSize.y + absoluteSize.h) ) | |||
| 14229 | { | |||
| 14230 | dropDownOptionSelected = -1; | |||
| 14231 | } | |||
| 14232 | } | |||
| 14233 | ||||
| 14234 | if ( dropDownOptionSelected >= 0 && dropDownOptionSelected < dropDown.options.size() ) | |||
| 14235 | { | |||
| 14236 | auto txt = std::get<1>(optionFrames[dropDownOptionSelected]); | |||
| ||||
| 14237 | txt->setColor(hudColors.itemContextMenuOptionSelectedText); | |||
| 14238 | SDL_Rect size = txt->getSize(); | |||
| 14239 | size.x -= 4; | |||
| 14240 | size.w += 2 * 4; | |||
| 14241 | size.y += 3; | |||
| 14242 | highlightImageMid->pos = size; | |||
| 14243 | highlightImageMid->pos.x += highlightImageLeft->pos.w; | |||
| 14244 | highlightImageMid->pos.w -= 2 * highlightImageLeft->pos.w; | |||
| 14245 | highlightImageMid->pos.h = highlightImageLeft->pos.h; | |||
| 14246 | highlightImageMid->disabled = false; | |||
| 14247 | ||||
| 14248 | highlightImageLeft->pos.x = highlightImageMid->pos.x - highlightImageLeft->pos.w; | |||
| 14249 | highlightImageLeft->pos.y = highlightImageMid->pos.y; | |||
| 14250 | highlightImageLeft->disabled = false; | |||
| 14251 | highlightImageRight->pos.x = highlightImageMid->pos.x + highlightImageMid->pos.w; | |||
| 14252 | highlightImageRight->disabled = false; | |||
| 14253 | highlightImageRight->pos.y = highlightImageMid->pos.y; | |||
| 14254 | } | |||
| 14255 | ||||
| 14256 | bool activate = false; | |||
| 14257 | if ( !dropDownToggleClick && !Input::inputs[player.playernum].binary("MenuRightClick") ) | |||
| 14258 | { | |||
| 14259 | activate = true; | |||
| 14260 | if ( dropDownOptionSelected >= 0 && dropDownOptionSelected < dropDown.options.size() ) | |||
| 14261 | { | |||
| 14262 | Player::soundActivate(); | |||
| 14263 | } | |||
| 14264 | } | |||
| 14265 | else if ( dropDownToggleClick ) | |||
| 14266 | { | |||
| 14267 | if ( Input::inputs[player.playernum].consumeBinaryToggle("MenuRightClick") ) | |||
| 14268 | { | |||
| 14269 | close(); | |||
| 14270 | } | |||
| 14271 | else if ( Input::inputs[player.playernum].consumeBinaryToggle("MenuConfirm") ) | |||
| 14272 | { | |||
| 14273 | activate = true; | |||
| 14274 | if ( dropDownOptionSelected >= 0 && dropDownOptionSelected < dropDown.options.size() ) | |||
| 14275 | { | |||
| 14276 | Player::soundActivate(); | |||
| 14277 | } | |||
| 14278 | } | |||
| 14279 | else if ( Input::inputs[player.playernum].consumeBinaryToggle("MenuCancel") ) | |||
| 14280 | { | |||
| 14281 | close(); | |||
| 14282 | Player::soundCancel(); | |||
| 14283 | } | |||
| 14284 | } | |||
| 14285 | ||||
| 14286 | if ( !(player.bControlEnabled && !gamePaused && !player.usingCommand()) ) | |||
| 14287 | { | |||
| 14288 | close(); | |||
| 14289 | } | |||
| 14290 | else if ( activate ) | |||
| 14291 | { | |||
| 14292 | if ( dropDownOptionSelected >= 0 && dropDownOptionSelected < dropDown.options.size() ) | |||
| 14293 | { | |||
| 14294 | if ( currentName == "item_interact" || currentName == "hotbar_interact" | |||
| 14295 | || currentName == "chest_interact" || currentName == "spell_interact" ) | |||
| 14296 | { | |||
| 14297 | if ( item && dropDownOptionSelected < contextOptions.size() ) | |||
| 14298 | { | |||
| 14299 | if ( contextOptions[dropDownOptionSelected] == ItemContextMenuPrompts::PROMPT_DROP | |||
| 14300 | && player.paperDoll.isItemOnDoll(*item) ) | |||
| 14301 | { | |||
| 14302 | // need to unequip | |||
| 14303 | player.inventoryUI.activateItemContextMenuOption(item, ItemContextMenuPrompts::PROMPT_UNEQUIP_FOR_DROP); | |||
| 14304 | player.paperDoll.updateSlots(); | |||
| 14305 | if ( player.paperDoll.isItemOnDoll(*item) ) | |||
| 14306 | { | |||
| 14307 | // couldn't unequip, no more actions | |||
| 14308 | } | |||
| 14309 | else | |||
| 14310 | { | |||
| 14311 | // successfully unequipped, let's drop it. | |||
| 14312 | bool droppedAll = false; | |||
| 14313 | while ( item && item->count > 1 ) | |||
| 14314 | { | |||
| 14315 | droppedAll = dropItem(item, player.playernum); | |||
| 14316 | if ( droppedAll ) | |||
| 14317 | { | |||
| 14318 | item = nullptr; | |||
| 14319 | } | |||
| 14320 | } | |||
| 14321 | if ( !droppedAll ) | |||
| 14322 | { | |||
| 14323 | dropItem(item, player.playernum); | |||
| 14324 | } | |||
| 14325 | } | |||
| 14326 | } | |||
| 14327 | else | |||
| 14328 | { | |||
| 14329 | player.inventoryUI.activateItemContextMenuOption(item, contextOptions[dropDownOptionSelected]); | |||
| 14330 | } | |||
| 14331 | } | |||
| 14332 | } | |||
| 14333 | else | |||
| 14334 | { | |||
| 14335 | activateSelection(currentName, dropDownOptionSelected); | |||
| 14336 | } | |||
| 14337 | } | |||
| 14338 | //Close the menu. | |||
| 14339 | close(); | |||
| 14340 | } | |||
| 14341 | } | |||
| 14342 | ||||
| 14343 | void Player::GUIDropdown_t::close() | |||
| 14344 | { | |||
| 14345 | if ( dropdownFrame ) | |||
| 14346 | { | |||
| 14347 | dropdownFrame->setHollow(true); | |||
| 14348 | dropdownFrame->removeSelf(); | |||
| 14349 | dropdownFrame = nullptr; | |||
| 14350 | } | |||
| 14351 | if ( dropdownBlockClickFrame ) | |||
| 14352 | { | |||
| 14353 | dropdownBlockClickFrame->setHollow(true); | |||
| 14354 | dropdownBlockClickFrame->removeSelf(); | |||
| 14355 | dropdownBlockClickFrame = nullptr; | |||
| 14356 | } | |||
| 14357 | dropDownOptionSelected = 0; | |||
| 14358 | dropDownItem = 0; | |||
| 14359 | bOpen = false; | |||
| 14360 | dropDownToggleClick = false; | |||
| 14361 | currentName = ""; | |||
| 14362 | bClosedThisTick = true; | |||
| 14363 | } | |||
| 14364 | ||||
| 14365 | ||||
| 14366 | void Player::GUI_t::closeDropdowns() | |||
| 14367 | { | |||
| 14368 | if ( dropdownMenu.bOpen ) | |||
| 14369 | { | |||
| 14370 | dropdownMenu.close(); | |||
| 14371 | } | |||
| 14372 | if ( inputs.getUIInteraction(player.playernum)->itemMenuOpen ) | |||
| 14373 | { | |||
| 14374 | inputs.getUIInteraction(player.playernum)->itemMenuOpen = false; | |||
| 14375 | player.inventoryUI.updateItemContextMenu(); | |||
| 14376 | } | |||
| 14377 | } | |||
| 14378 | bool Player::GUI_t::isDropdownActive() | |||
| 14379 | { | |||
| 14380 | if ( dropdownMenu.bOpen ) | |||
| 14381 | { | |||
| 14382 | return true; | |||
| 14383 | } | |||
| 14384 | if ( inputs.getUIInteraction(player.playernum)->itemMenuOpen ) | |||
| 14385 | { | |||
| 14386 | return true; | |||
| 14387 | } | |||
| 14388 | return false; | |||
| 14389 | } | |||
| 14390 | ||||
| 14391 | void Player::GUIDropdown_t::open(const std::string name) | |||
| 14392 | { | |||
| 14393 | set(name); | |||
| 14394 | assert(dropdownFrame)(static_cast<void> (0)); | |||
| 14395 | if ( bOpen ) | |||
| 14396 | { | |||
| 14397 | return; | |||
| 14398 | } | |||
| 14399 | ||||
| 14400 | if ( !inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 14401 | { | |||
| 14402 | Player::soundActivate(); | |||
| 14403 | } | |||
| 14404 | bOpen = true; | |||
| 14405 | bClosedThisTick = false; | |||
| 14406 | ||||
| 14407 | // clear inventory item context menu stuff | |||
| 14408 | bool& itemMenuOpen = inputs.getUIInteraction(player.playernum)->itemMenuOpen; | |||
| 14409 | itemMenuOpen = false; | |||
| 14410 | ||||
| 14411 | if ( inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 14412 | { | |||
| 14413 | dropDownX = (inputs.getMouse(player.playernum, Inputs::X) / (float)xres) * (float)Frame::virtualScreenX + (getDropDownAlignRight(name) ? 8 : -8); | |||
| 14414 | dropDownY = (inputs.getMouse(player.playernum, Inputs::Y) / (float)yres) * (float)Frame::virtualScreenY; | |||
| 14415 | if ( auto interactMenuTop = dropdownFrame->findImage("interact top background") ) | |||
| 14416 | { | |||
| 14417 | // 10px is slot half height, minus the top interact text height | |||
| 14418 | // mouse will be situated halfway in first menu option | |||
| 14419 | dropDownY -= (interactMenuTop->pos.h + 10 + 2); | |||
| 14420 | } | |||
| 14421 | if ( dropDownX % 2 == 1 ) | |||
| 14422 | { | |||
| 14423 | ++dropDownX; // even pixel adjustment | |||
| 14424 | } | |||
| 14425 | if ( dropDownY % 2 == 1 ) | |||
| 14426 | { | |||
| 14427 | ++dropDownY; // even pixel adjustment | |||
| 14428 | } | |||
| 14429 | } | |||
| 14430 | dropDownOptionSelected = 0; | |||
| 14431 | if ( allDropDowns[name].defaultOption > 0 && allDropDowns[name].options.size() > allDropDowns[name].defaultOption ) | |||
| 14432 | { | |||
| 14433 | if ( auto txt = dropdownFrame->findField("interact option 1") ) | |||
| 14434 | { | |||
| 14435 | dropDownY -= txt->getSize().h; | |||
| 14436 | dropDownOptionSelected = allDropDowns[name].defaultOption; | |||
| 14437 | } | |||
| 14438 | } | |||
| 14439 | if ( auto highlightImageMid = dropdownFrame->findImage("interact selected highlight mid") ) | |||
| 14440 | { | |||
| 14441 | highlightImageMid->disabled = true; | |||
| 14442 | } | |||
| 14443 | if ( auto highlightImageLeft = dropdownFrame->findImage("interact selected highlight left") ) | |||
| 14444 | { | |||
| 14445 | highlightImageLeft->disabled = true; | |||
| 14446 | } | |||
| 14447 | if ( auto highlightImageRight = dropdownFrame->findImage("interact selected highlight right") ) | |||
| 14448 | { | |||
| 14449 | highlightImageRight->disabled = true; | |||
| 14450 | } | |||
| 14451 | ||||
| 14452 | //Default reset. Otherwise will break mouse support after using gamepad once to trigger a context menu. | |||
| 14453 | dropDownToggleClick = false; | |||
| 14454 | ||||
| 14455 | if ( inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 14456 | { | |||
| 14457 | player.hud.cursor.lastUpdateTick = ticks; | |||
| 14458 | } | |||
| 14459 | } | |||
| 14460 | ||||
| 14461 | void Player::GUIDropdown_t::create(const std::string name) | |||
| 14462 | { | |||
| 14463 | if ( dropdownFrame ) | |||
| 14464 | { | |||
| 14465 | dropdownFrame->removeSelf(); | |||
| 14466 | dropdownFrame = nullptr; | |||
| 14467 | } | |||
| 14468 | if ( dropdownBlockClickFrame ) | |||
| 14469 | { | |||
| 14470 | dropdownBlockClickFrame->removeSelf(); | |||
| 14471 | dropdownBlockClickFrame = nullptr; | |||
| 14472 | } | |||
| 14473 | ||||
| 14474 | auto& dropDown = allDropDowns[name]; | |||
| 14475 | ||||
| 14476 | char dropdownBlockClickName[64] = ""; | |||
| 14477 | snprintf(dropdownBlockClickName, sizeof(dropdownBlockClickName), "player dropdown block click %d", player.playernum); | |||
| 14478 | dropdownBlockClickFrame = gameUIFrame[player.playernum]->addFrame(dropdownBlockClickName); | |||
| 14479 | dropdownBlockClickFrame->setSize(SDL_Rect{ players[player.playernum]->camera_virtualx1(), | |||
| 14480 | players[player.playernum]->camera_virtualy1(), | |||
| 14481 | players[player.playernum]->camera_virtualWidth(), | |||
| 14482 | players[player.playernum]->camera_virtualHeight()}); | |||
| 14483 | dropdownBlockClickFrame->setOwner(player.playernum); | |||
| 14484 | ||||
| 14485 | char dropdownName[64] = ""; | |||
| 14486 | snprintf(dropdownName, sizeof(dropdownName), "player dropdown %d", player.playernum); | |||
| 14487 | dropdownFrame = gameUIFrame[player.playernum]->addFrame(dropdownName); | |||
| 14488 | const int interactWidth = 106; | |||
| 14489 | dropdownFrame->setSize(SDL_Rect{ 0, 0, interactWidth + 6 * 2, 100 }); | |||
| 14490 | dropdownFrame->setDisabled(true); | |||
| 14491 | dropdownFrame->setInheritParentFrameOpacity(false); | |||
| 14492 | ||||
| 14493 | Uint32 color = makeColor( 255, 255, 255, 255); | |||
| 14494 | const int topBackgroundHeight = 30; | |||
| 14495 | const int optionHeight = 20; | |||
| 14496 | ||||
| 14497 | dropdownFrame->addImage(SDL_Rect{ 24, 0, 0, 30 }, | |||
| 14498 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_T03.png", "interact top background"); | |||
| 14499 | dropdownFrame->addImage(SDL_Rect{ 0, 0, 24, 30 }, | |||
| 14500 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_TL03.png", "interact top left"); | |||
| 14501 | dropdownFrame->addImage(SDL_Rect{ 0, 0, 24, 30 }, | |||
| 14502 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_TR03.png", "interact top right"); | |||
| 14503 | ||||
| 14504 | dropdownFrame->addImage(SDL_Rect{ 24, 30, 0, 12 }, | |||
| 14505 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_C03.png", "interact middle background"); | |||
| 14506 | auto ml = dropdownFrame->addImage(SDL_Rect{ 0, 30, 24, 12 }, | |||
| 14507 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_L03.png", "interact middle left"); | |||
| 14508 | ml->tiled = true; | |||
| 14509 | auto mr = dropdownFrame->addImage(SDL_Rect{ 0, 30, 24, 12 }, | |||
| 14510 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_R03.png", "interact middle right"); | |||
| 14511 | mr->tiled = true; | |||
| 14512 | ||||
| 14513 | dropdownFrame->addImage(SDL_Rect{ 24, 96, 0, 14 }, | |||
| 14514 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_B03.png", "interact bottom background"); | |||
| 14515 | dropdownFrame->addImage(SDL_Rect{ 0, 96, 24, 14 }, | |||
| 14516 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_BL03.png", "interact bottom left"); | |||
| 14517 | dropdownFrame->addImage(SDL_Rect{ 0, 96, 24, 14 }, | |||
| 14518 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_BR03.png", "interact bottom right"); | |||
| 14519 | ||||
| 14520 | auto selectmid = dropdownFrame->addImage(SDL_Rect{ 6, optionHeight - 16, interactWidth, 22 }, | |||
| 14521 | hudColors.itemContextMenuOptionSelectedImg, "*#images/ui/Inventory/tooltips/HoverItemMenu_SelectBack_M03.png", "interact selected highlight mid"); | |||
| 14522 | selectmid->tiled = true; | |||
| 14523 | dropdownFrame->addImage(SDL_Rect{ 6, optionHeight - 16, 20, 22 }, | |||
| 14524 | hudColors.itemContextMenuOptionSelectedImg, "*#images/ui/Inventory/tooltips/HoverItemMenu_SelectBack_L03.png", "interact selected highlight left"); | |||
| 14525 | dropdownFrame->addImage(SDL_Rect{ 6, optionHeight - 16, 20, 22 }, | |||
| 14526 | hudColors.itemContextMenuOptionSelectedImg, "*#images/ui/Inventory/tooltips/HoverItemMenu_SelectBack_R03.png", "interact selected highlight right"); | |||
| 14527 | ||||
| 14528 | const char* interactFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 14529 | ||||
| 14530 | auto interactText = dropdownFrame->addField("interact text", 32); | |||
| 14531 | interactText->setText(dropDown.title.c_str()); | |||
| 14532 | interactText->setSize(SDL_Rect{ 0, 2, 0, topBackgroundHeight }); | |||
| 14533 | interactText->setFont(interactFont); | |||
| 14534 | interactText->setHJustify(Field::justify_t::CENTER); | |||
| 14535 | interactText->setVJustify(Field::justify_t::CENTER); | |||
| 14536 | interactText->setColor(hudColors.itemContextMenuHeadingText); | |||
| 14537 | ||||
| 14538 | const int interactOptionStartX = 4; | |||
| 14539 | const int interactOptionStartY = 33; | |||
| 14540 | const int glyphSize = 20; | |||
| 14541 | const int textWidth = 80; | |||
| 14542 | const int textHeight = glyphSize + 8; | |||
| 14543 | ||||
| 14544 | Uint32 textColor = hudColors.itemContextMenuOptionText; | |||
| 14545 | SDL_Rect prevGlyphPos; | |||
| 14546 | ||||
| 14547 | for ( int i = 1; i <= dropDown.options.size(); ++i ) | |||
| 14548 | { | |||
| 14549 | char glyphname[32] = ""; | |||
| 14550 | snprintf(glyphname, sizeof(glyphname), "glyph %d", i); | |||
| 14551 | Frame::image_t* interactGlyph = nullptr; | |||
| 14552 | if ( i == 1 ) | |||
| 14553 | { | |||
| 14554 | interactGlyph = dropdownFrame->addImage( | |||
| 14555 | SDL_Rect{ interactOptionStartX + 4, interactOptionStartY + 4, glyphSize, glyphSize }, | |||
| 14556 | 0xFFFFFFFF, "", glyphname); | |||
| 14557 | } | |||
| 14558 | else if ( i > 1 ) | |||
| 14559 | { | |||
| 14560 | interactGlyph = dropdownFrame->addImage( | |||
| 14561 | SDL_Rect{ interactOptionStartX + 4, | |||
| 14562 | prevGlyphPos.y + prevGlyphPos.h + 4, | |||
| 14563 | glyphSize, glyphSize }, | |||
| 14564 | 0xFFFFFFFF, "", glyphname); | |||
| 14565 | } | |||
| 14566 | ||||
| 14567 | const int textAlignX = interactGlyph->pos.x + interactGlyph->pos.w + 6; | |||
| 14568 | int textAlignY = interactGlyph->pos.y - 10; | |||
| 14569 | if ( i == 1 ) | |||
| 14570 | { | |||
| 14571 | textAlignY = interactGlyph->pos.y - 8; | |||
| 14572 | } | |||
| 14573 | ||||
| 14574 | char optionname[32] = ""; | |||
| 14575 | snprintf(optionname, sizeof(optionname), "interact option %d", i); | |||
| 14576 | interactText = dropdownFrame->addField(optionname, 32); | |||
| 14577 | interactText->setText(""); | |||
| 14578 | interactText->setSize(SDL_Rect{ | |||
| 14579 | textAlignX, | |||
| 14580 | textAlignY, | |||
| 14581 | textWidth, textHeight }); | |||
| 14582 | interactText->setFont(interactFont); | |||
| 14583 | interactText->setHJustify(Field::justify_t::LEFT); | |||
| 14584 | interactText->setVJustify(Field::justify_t::CENTER); | |||
| 14585 | interactText->setColor(textColor); | |||
| 14586 | ||||
| 14587 | prevGlyphPos = interactGlyph->pos; | |||
| 14588 | } | |||
| 14589 | } | |||
| 14590 | ||||
| 14591 | void Player::CharacterSheet_t::selectElement(SheetElements element, bool usingMouse, bool moveCursor) | |||
| 14592 | { | |||
| 14593 | selectedElement = element; | |||
| 14594 | ||||
| 14595 | Frame* elementFrame = nullptr; | |||
| 14596 | Frame::image_t* img = nullptr; | |||
| 14597 | Field* elementField = nullptr; | |||
| 14598 | Button* elementButton = nullptr; | |||
| 14599 | bool selectedAButton = false; | |||
| 14600 | switch ( element ) | |||
| 14601 | { | |||
| 14602 | case SHEET_OPEN_LOG: | |||
| 14603 | if ( elementFrame = sheetFrame->findFrame("log map buttons") ) | |||
| 14604 | { | |||
| 14605 | if ( !inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 14606 | { | |||
| 14607 | elementFrame->findButton("log button")->select(); | |||
| 14608 | selectedAButton = true; | |||
| 14609 | } | |||
| 14610 | elementFrame = elementFrame->findFrame("log button selector"); | |||
| 14611 | //img = elementFrame->findImage("log button img"); | |||
| 14612 | } | |||
| 14613 | break; | |||
| 14614 | case SHEET_OPEN_MAP: | |||
| 14615 | if ( elementFrame = sheetFrame->findFrame("log map buttons") ) | |||
| 14616 | { | |||
| 14617 | if ( !inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 14618 | { | |||
| 14619 | elementFrame->findButton("map button")->select(); | |||
| 14620 | selectedAButton = true; | |||
| 14621 | } | |||
| 14622 | elementFrame = elementFrame->findFrame("map button selector"); | |||
| 14623 | //img = elementFrame->findImage("map button img"); | |||
| 14624 | } | |||
| 14625 | break; | |||
| 14626 | case SHEET_SKILL_LIST: | |||
| 14627 | elementFrame = sheetFrame->findFrame("skills button frame"); | |||
| 14628 | if ( !inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 14629 | { | |||
| 14630 | elementFrame->findButton("skills button")->select(); | |||
| 14631 | selectedAButton = true; | |||
| 14632 | } | |||
| 14633 | break; | |||
| 14634 | case SHEET_TIMER: | |||
| 14635 | elementFrame = sheetFrame->findFrame("game timer"); | |||
| 14636 | if ( !inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 14637 | { | |||
| 14638 | elementFrame->findButton("timer selector")->select(); | |||
| 14639 | selectedAButton = true; | |||
| 14640 | } | |||
| 14641 | break; | |||
| 14642 | case SHEET_GOLD: | |||
| 14643 | if ( elementFrame = sheetFrame->findFrame("character info") ) | |||
| 14644 | { | |||
| 14645 | if ( elementFrame = elementFrame->findFrame("character info inner frame") ) | |||
| 14646 | { | |||
| 14647 | elementButton = elementFrame->findButton("character gold selector"); | |||
| 14648 | } | |||
| 14649 | } | |||
| 14650 | break; | |||
| 14651 | case SHEET_DUNGEON_FLOOR: | |||
| 14652 | if ( elementFrame = sheetFrame->findFrame("dungeon floor frame") ) | |||
| 14653 | { | |||
| 14654 | elementButton = elementFrame->findButton("dungeon floor selector"); | |||
| 14655 | } | |||
| 14656 | break; | |||
| 14657 | case SHEET_CHAR_CLASS: | |||
| 14658 | if ( elementFrame = sheetFrame->findFrame("character info") ) | |||
| 14659 | { | |||
| 14660 | if ( elementFrame = elementFrame->findFrame("character info inner frame") ) | |||
| 14661 | { | |||
| 14662 | elementButton = elementFrame->findButton("character class selector"); | |||
| 14663 | } | |||
| 14664 | } | |||
| 14665 | break; | |||
| 14666 | case SHEET_CHAR_RACE_SEX: | |||
| 14667 | if ( elementFrame = sheetFrame->findFrame("character info") ) | |||
| 14668 | { | |||
| 14669 | if ( elementFrame = elementFrame->findFrame("character info inner frame") ) | |||
| 14670 | { | |||
| 14671 | elementButton = elementFrame->findButton("character race selector"); | |||
| 14672 | } | |||
| 14673 | } | |||
| 14674 | break; | |||
| 14675 | case SHEET_STR: | |||
| 14676 | if ( elementFrame = sheetFrame->findFrame("stats") ) | |||
| 14677 | { | |||
| 14678 | if ( elementFrame = elementFrame->findFrame("stats inner frame") ) | |||
| 14679 | { | |||
| 14680 | elementButton = elementFrame->findButton("str button"); | |||
| 14681 | } | |||
| 14682 | } | |||
| 14683 | break; | |||
| 14684 | case SHEET_DEX: | |||
| 14685 | if ( elementFrame = sheetFrame->findFrame("stats") ) | |||
| 14686 | { | |||
| 14687 | if ( elementFrame = elementFrame->findFrame("stats inner frame") ) | |||
| 14688 | { | |||
| 14689 | elementButton = elementFrame->findButton("dex button"); | |||
| 14690 | } | |||
| 14691 | } | |||
| 14692 | break; | |||
| 14693 | case SHEET_CON: | |||
| 14694 | if ( elementFrame = sheetFrame->findFrame("stats") ) | |||
| 14695 | { | |||
| 14696 | if ( elementFrame = elementFrame->findFrame("stats inner frame") ) | |||
| 14697 | { | |||
| 14698 | elementButton = elementFrame->findButton("con button"); | |||
| 14699 | } | |||
| 14700 | } | |||
| 14701 | break; | |||
| 14702 | case SHEET_INT: | |||
| 14703 | if ( elementFrame = sheetFrame->findFrame("stats") ) | |||
| 14704 | { | |||
| 14705 | if ( elementFrame = elementFrame->findFrame("stats inner frame") ) | |||
| 14706 | { | |||
| 14707 | elementButton = elementFrame->findButton("int button"); | |||
| 14708 | } | |||
| 14709 | } | |||
| 14710 | break; | |||
| 14711 | case SHEET_PER: | |||
| 14712 | if ( elementFrame = sheetFrame->findFrame("stats") ) | |||
| 14713 | { | |||
| 14714 | if ( elementFrame = elementFrame->findFrame("stats inner frame") ) | |||
| 14715 | { | |||
| 14716 | elementButton = elementFrame->findButton("per button"); | |||
| 14717 | } | |||
| 14718 | } | |||
| 14719 | break; | |||
| 14720 | case SHEET_CHR: | |||
| 14721 | if ( elementFrame = sheetFrame->findFrame("stats") ) | |||
| 14722 | { | |||
| 14723 | if ( elementFrame = elementFrame->findFrame("stats inner frame") ) | |||
| 14724 | { | |||
| 14725 | elementButton = elementFrame->findButton("chr button"); | |||
| 14726 | } | |||
| 14727 | } | |||
| 14728 | break; | |||
| 14729 | case SHEET_ATK: | |||
| 14730 | if ( elementFrame = sheetFrame->findFrame("attributes") ) | |||
| 14731 | { | |||
| 14732 | if ( elementFrame = elementFrame->findFrame("attributes inner frame") ) | |||
| 14733 | { | |||
| 14734 | elementButton = elementFrame->findButton("atk button"); | |||
| 14735 | } | |||
| 14736 | } | |||
| 14737 | break; | |||
| 14738 | case SHEET_AC: | |||
| 14739 | if ( elementFrame = sheetFrame->findFrame("attributes") ) | |||
| 14740 | { | |||
| 14741 | if ( elementFrame = elementFrame->findFrame("attributes inner frame") ) | |||
| 14742 | { | |||
| 14743 | elementButton = elementFrame->findButton("ac button"); | |||
| 14744 | } | |||
| 14745 | } | |||
| 14746 | break; | |||
| 14747 | case SHEET_POW: | |||
| 14748 | if ( elementFrame = sheetFrame->findFrame("attributes") ) | |||
| 14749 | { | |||
| 14750 | if ( elementFrame = elementFrame->findFrame("attributes inner frame") ) | |||
| 14751 | { | |||
| 14752 | elementButton = elementFrame->findButton("pow button"); | |||
| 14753 | } | |||
| 14754 | } | |||
| 14755 | break; | |||
| 14756 | case SHEET_RES: | |||
| 14757 | if ( elementFrame = sheetFrame->findFrame("attributes") ) | |||
| 14758 | { | |||
| 14759 | if ( elementFrame = elementFrame->findFrame("attributes inner frame") ) | |||
| 14760 | { | |||
| 14761 | elementButton = elementFrame->findButton("res button"); | |||
| 14762 | } | |||
| 14763 | } | |||
| 14764 | break; | |||
| 14765 | case SHEET_RGN: | |||
| 14766 | if ( elementFrame = sheetFrame->findFrame("attributes") ) | |||
| 14767 | { | |||
| 14768 | if ( elementFrame = elementFrame->findFrame("attributes inner frame") ) | |||
| 14769 | { | |||
| 14770 | elementButton = elementFrame->findButton("rgn button"); | |||
| 14771 | } | |||
| 14772 | } | |||
| 14773 | break; | |||
| 14774 | case SHEET_RGN_MP: | |||
| 14775 | if ( elementFrame = sheetFrame->findFrame("attributes") ) | |||
| 14776 | { | |||
| 14777 | if ( elementFrame = elementFrame->findFrame("attributes inner frame") ) | |||
| 14778 | { | |||
| 14779 | elementButton = elementFrame->findButton("rgn mp button"); | |||
| 14780 | } | |||
| 14781 | } | |||
| 14782 | break; | |||
| 14783 | case SHEET_WGT: | |||
| 14784 | if ( elementFrame = sheetFrame->findFrame("attributes") ) | |||
| 14785 | { | |||
| 14786 | if ( elementFrame = elementFrame->findFrame("attributes inner frame") ) | |||
| 14787 | { | |||
| 14788 | elementButton = elementFrame->findButton("wgt button"); | |||
| 14789 | } | |||
| 14790 | } | |||
| 14791 | break; | |||
| 14792 | default: | |||
| 14793 | elementFrame = nullptr; | |||
| 14794 | break; | |||
| 14795 | } | |||
| 14796 | ||||
| 14797 | SDL_Rect pos{ 0, 0, 0, 0 }; | |||
| 14798 | if ( elementFrame && moveCursor ) | |||
| 14799 | { | |||
| 14800 | elementFrame->warpMouseToFrame(player.playernum, (Inputs::SET_CONTROLLER)); | |||
| 14801 | pos = elementFrame->getAbsoluteSize(); | |||
| 14802 | if ( img ) | |||
| 14803 | { | |||
| 14804 | pos.x += img->pos.x; | |||
| 14805 | pos.y += img->pos.y; | |||
| 14806 | pos.w = img->pos.w; | |||
| 14807 | pos.h = img->pos.h; | |||
| 14808 | } | |||
| 14809 | if ( elementButton ) | |||
| 14810 | { | |||
| 14811 | pos = elementButton->getAbsoluteSize(); | |||
| 14812 | } | |||
| 14813 | if ( elementField ) | |||
| 14814 | { | |||
| 14815 | pos = elementField->getAbsoluteSize(); | |||
| 14816 | } | |||
| 14817 | // make sure to adjust absolute size to camera viewport | |||
| 14818 | pos.x -= player.camera_virtualx1(); | |||
| 14819 | pos.y -= player.camera_virtualy1(); | |||
| 14820 | player.hud.setCursorDisabled(false); | |||
| 14821 | if ( !isInteractable ) | |||
| 14822 | { | |||
| 14823 | player.characterSheet.queuedElement = player.characterSheet.selectedElement; | |||
| 14824 | } | |||
| 14825 | else | |||
| 14826 | { | |||
| 14827 | player.characterSheet.queuedElement = SHEET_UNSELECTED; | |||
| 14828 | player.hud.updateCursorAnimation(pos.x - 1, pos.y - 1, pos.w, pos.h, usingMouse); | |||
| 14829 | } | |||
| 14830 | } | |||
| 14831 | if ( !selectedAButton && elementFrame && !inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 14832 | { | |||
| 14833 | if ( elementButton ) | |||
| 14834 | { | |||
| 14835 | elementButton->select(); | |||
| 14836 | } | |||
| 14837 | else | |||
| 14838 | { | |||
| 14839 | elementFrame->select(); | |||
| 14840 | } | |||
| 14841 | } | |||
| 14842 | } | |||
| 14843 | ||||
| 14844 | void Player::CharacterSheet_t::updateGameTimer() | |||
| 14845 | { | |||
| 14846 | auto characterInfoFrame = sheetFrame->findFrame("character info"); | |||
| 14847 | auto timerFrame = sheetFrame->findFrame("game timer"); | |||
| 14848 | auto timerText = timerFrame->findField("timer text"); | |||
| 14849 | char buf[32]; | |||
| 14850 | ||||
| 14851 | Uint32 sec = (completionTime / TICKS_PER_SECOND50) % 60; | |||
| 14852 | Uint32 min = ((completionTime / TICKS_PER_SECOND50) / 60) % 60; | |||
| 14853 | Uint32 hour = (((completionTime / TICKS_PER_SECOND50) / 60) / 60) % 24; | |||
| 14854 | Uint32 day = ((completionTime / TICKS_PER_SECOND50) / 60) / 60 / 24; | |||
| 14855 | snprintf(buf, sizeof(buf), "%02d:%02d:%02d:%02d", day, hour, min, sec); | |||
| 14856 | timerText->setText(buf); | |||
| 14857 | ||||
| 14858 | bool enableTooltips = !player.GUI.isDropdownActive() && !player.GUI.dropdownMenu.bClosedThisTick && inputs.getVirtualMouse(player.playernum)->draw_cursor; | |||
| 14859 | ||||
| 14860 | bool bCompactView = player.bUseCompactGUIHeight(); | |||
| 14861 | if ( bCompactView ) | |||
| 14862 | { | |||
| 14863 | enableTooltips = false; | |||
| 14864 | } | |||
| 14865 | ||||
| 14866 | if ( selectedElement == SHEET_TIMER && enableTooltips ) | |||
| 14867 | { | |||
| 14868 | SDL_Rect tooltipPos = characterInfoFrame->getSize(); | |||
| 14869 | tooltipPos.y = timerFrame->getSize().y; | |||
| 14870 | Player::PanelJustify_t tooltipJustify = PANEL_JUSTIFY_RIGHT; | |||
| 14871 | if ( (panelJustify == PANEL_JUSTIFY_LEFT && !bCompactView) || (panelJustify == PANEL_JUSTIFY_RIGHT && bCompactView) ) | |||
| 14872 | { | |||
| 14873 | tooltipJustify = PANEL_JUSTIFY_LEFT; | |||
| 14874 | tooltipPos.x += tooltipPos.w; | |||
| 14875 | } | |||
| 14876 | updateCharacterSheetTooltip(SHEET_TIMER, tooltipPos, tooltipJustify); | |||
| 14877 | } | |||
| 14878 | } | |||
| 14879 | ||||
| 14880 | std::string& Player::CharacterSheet_t::getHoverTextString(std::string key) | |||
| 14881 | { | |||
| 14882 | if ( hoverTextStrings.find(key) != hoverTextStrings.end() ) | |||
| 14883 | { | |||
| 14884 | return hoverTextStrings[key]; | |||
| 14885 | } | |||
| 14886 | return defaultString; | |||
| 14887 | } | |||
| 14888 | ||||
| 14889 | bool getAttackTooltipLines(int playernum, AttackHoverText_t& attackHoverTextInfo, int lineNumber, char titleBuf[128], char valueBuf[128]) | |||
| 14890 | { | |||
| 14891 | std::string skillName = "-"; | |||
| 14892 | Sint32 skillLVL = 0; | |||
| 14893 | for ( auto& skill : Player::SkillSheet_t::skillSheetData.skillEntries ) | |||
| 14894 | { | |||
| 14895 | if ( skill.skillId == attackHoverTextInfo.proficiency ) | |||
| 14896 | { | |||
| 14897 | skillName = skill.name; | |||
| 14898 | skillLVL = stats[playernum]->getModifiedProficiency(attackHoverTextInfo.proficiency); | |||
| 14899 | break; | |||
| 14900 | } | |||
| 14901 | } | |||
| 14902 | ||||
| 14903 | if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_MELEE_WEAPON ) | |||
| 14904 | { | |||
| 14905 | switch ( lineNumber ) | |||
| 14906 | { | |||
| 14907 | case 1: | |||
| 14908 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_avg").c_str()); | |||
| 14909 | snprintf(valueBuf, 127, | |||
| 14910 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_average_format").c_str(), | |||
| 14911 | (real_t)attackHoverTextInfo.attackMinRange + ((attackHoverTextInfo.attackMaxRange - attackHoverTextInfo.attackMinRange) / 2.0)); | |||
| 14912 | return true; | |||
| 14913 | case 2: | |||
| 14914 | snprintf(titleBuf, 127, Player::CharacterSheet_t::getHoverTextString("attributes_atk_range").c_str(), | |||
| 14915 | skillName.c_str(), skillLVL); | |||
| 14916 | snprintf(valueBuf, 127, | |||
| 14917 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_range_format").c_str(), | |||
| 14918 | attackHoverTextInfo.attackMinRange, attackHoverTextInfo.attackMaxRange); | |||
| 14919 | return true; | |||
| 14920 | case 3: | |||
| 14921 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_attr_bonus_melee").c_str()); | |||
| 14922 | snprintf(valueBuf, 127, | |||
| 14923 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 14924 | attackHoverTextInfo.mainAttributeBonus); | |||
| 14925 | return true; | |||
| 14926 | case 4: | |||
| 14927 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_weapon_bonus").c_str()); | |||
| 14928 | snprintf(valueBuf, 127, | |||
| 14929 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 14930 | attackHoverTextInfo.weaponBonus); | |||
| 14931 | return true; | |||
| 14932 | case 5: | |||
| 14933 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_melee_weapon_base").c_str()); | |||
| 14934 | snprintf(valueBuf, 127, | |||
| 14935 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 14936 | BASE_MELEE_DAMAGE); | |||
| 14937 | return true; | |||
| 14938 | case 6: | |||
| 14939 | return false; | |||
| 14940 | default: | |||
| 14941 | return false; | |||
| 14942 | } | |||
| 14943 | } | |||
| 14944 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_UNARMED ) | |||
| 14945 | { | |||
| 14946 | switch ( lineNumber ) | |||
| 14947 | { | |||
| 14948 | case 1: | |||
| 14949 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_avg").c_str()); | |||
| 14950 | snprintf(valueBuf, 127, | |||
| 14951 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_average_format").c_str(), | |||
| 14952 | (real_t)attackHoverTextInfo.attackMinRange + ((attackHoverTextInfo.attackMaxRange - attackHoverTextInfo.attackMinRange) / 2.0)); | |||
| 14953 | return true; | |||
| 14954 | case 2: | |||
| 14955 | snprintf(titleBuf, 127, Player::CharacterSheet_t::getHoverTextString("attributes_atk_range").c_str(), | |||
| 14956 | skillName.c_str(), skillLVL); | |||
| 14957 | snprintf(valueBuf, 127, | |||
| 14958 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_range_format").c_str(), | |||
| 14959 | attackHoverTextInfo.attackMinRange, attackHoverTextInfo.attackMaxRange); | |||
| 14960 | return true; | |||
| 14961 | case 3: | |||
| 14962 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_attr_bonus_melee").c_str()); | |||
| 14963 | snprintf(valueBuf, 127, | |||
| 14964 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 14965 | attackHoverTextInfo.mainAttributeBonus); | |||
| 14966 | return true; | |||
| 14967 | case 4: | |||
| 14968 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_items_bonus").c_str()); | |||
| 14969 | snprintf(valueBuf, 127, | |||
| 14970 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 14971 | attackHoverTextInfo.equipmentAndEffectBonus); | |||
| 14972 | return true; | |||
| 14973 | case 5: | |||
| 14974 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_skill_bonus").c_str()); | |||
| 14975 | snprintf(valueBuf, 127, | |||
| 14976 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 14977 | attackHoverTextInfo.proficiencyBonus); | |||
| 14978 | return true; | |||
| 14979 | case 6: | |||
| 14980 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_unarmed_weapon_base").c_str()); | |||
| 14981 | snprintf(valueBuf, 127, | |||
| 14982 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 14983 | BASE_PLAYER_UNARMED_DAMAGE); | |||
| 14984 | return true; | |||
| 14985 | default: | |||
| 14986 | return false; | |||
| 14987 | } | |||
| 14988 | } | |||
| 14989 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_PICKAXE ) | |||
| 14990 | { | |||
| 14991 | switch ( lineNumber ) | |||
| 14992 | { | |||
| 14993 | case 1: | |||
| 14994 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_avg").c_str()); | |||
| 14995 | snprintf(valueBuf, 127, | |||
| 14996 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_average_format").c_str(), | |||
| 14997 | (real_t)attackHoverTextInfo.attackMinRange + ((attackHoverTextInfo.attackMaxRange - attackHoverTextInfo.attackMinRange) / 2.0)); | |||
| 14998 | return true; | |||
| 14999 | case 2: | |||
| 15000 | snprintf(titleBuf, 127, Player::CharacterSheet_t::getHoverTextString("attributes_atk_range_noskill").c_str()); | |||
| 15001 | snprintf(valueBuf, 127, | |||
| 15002 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_range_format").c_str(), | |||
| 15003 | attackHoverTextInfo.attackMinRange, attackHoverTextInfo.attackMaxRange); | |||
| 15004 | return true; | |||
| 15005 | case 3: | |||
| 15006 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_attr_bonus_melee").c_str()); | |||
| 15007 | snprintf(valueBuf, 127, | |||
| 15008 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15009 | attackHoverTextInfo.mainAttributeBonus); | |||
| 15010 | return true; | |||
| 15011 | case 4: | |||
| 15012 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_weapon_bonus").c_str()); | |||
| 15013 | snprintf(valueBuf, 127, | |||
| 15014 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15015 | attackHoverTextInfo.weaponBonus); | |||
| 15016 | return true; | |||
| 15017 | case 5: | |||
| 15018 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_melee_weapon_base").c_str()); | |||
| 15019 | snprintf(valueBuf, 127, | |||
| 15020 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15021 | BASE_MELEE_DAMAGE); | |||
| 15022 | return true; | |||
| 15023 | default: | |||
| 15024 | return false; | |||
| 15025 | } | |||
| 15026 | } | |||
| 15027 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_RANGED ) | |||
| 15028 | { | |||
| 15029 | switch ( lineNumber ) | |||
| 15030 | { | |||
| 15031 | case 1: | |||
| 15032 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_avg").c_str()); | |||
| 15033 | snprintf(valueBuf, 127, | |||
| 15034 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_average_format").c_str(), | |||
| 15035 | (real_t)attackHoverTextInfo.attackMinRange + ((attackHoverTextInfo.attackMaxRange - attackHoverTextInfo.attackMinRange) / 2.0)); | |||
| 15036 | return true; | |||
| 15037 | case 2: | |||
| 15038 | snprintf(titleBuf, 127, Player::CharacterSheet_t::getHoverTextString("attributes_atk_range").c_str(), | |||
| 15039 | skillName.c_str(), skillLVL); | |||
| 15040 | snprintf(valueBuf, 127, | |||
| 15041 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_range_format").c_str(), | |||
| 15042 | attackHoverTextInfo.attackMinRange, attackHoverTextInfo.attackMaxRange); | |||
| 15043 | return true; | |||
| 15044 | case 3: | |||
| 15045 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_attr_bonus_ranged").c_str()); | |||
| 15046 | snprintf(valueBuf, 127, | |||
| 15047 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15048 | attackHoverTextInfo.mainAttributeBonus); | |||
| 15049 | return true; | |||
| 15050 | case 4: | |||
| 15051 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_weapon_bonus").c_str()); | |||
| 15052 | snprintf(valueBuf, 127, | |||
| 15053 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15054 | attackHoverTextInfo.weaponBonus); | |||
| 15055 | return true; | |||
| 15056 | case 5: | |||
| 15057 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_items_bonus").c_str()); | |||
| 15058 | snprintf(valueBuf, 127, | |||
| 15059 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15060 | attackHoverTextInfo.equipmentAndEffectBonus); | |||
| 15061 | return true; | |||
| 15062 | case 6: | |||
| 15063 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_ranged_weapon_base").c_str()); | |||
| 15064 | snprintf(valueBuf, 127, | |||
| 15065 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15066 | BASE_RANGED_DAMAGE); | |||
| 15067 | return true; | |||
| 15068 | default: | |||
| 15069 | return false; | |||
| 15070 | } | |||
| 15071 | } | |||
| 15072 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_THROWN | |||
| 15073 | || attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_THROWN_GEM ) | |||
| 15074 | { | |||
| 15075 | switch ( lineNumber ) | |||
| 15076 | { | |||
| 15077 | case 1: | |||
| 15078 | snprintf(titleBuf, 127, Player::CharacterSheet_t::getHoverTextString("attributes_atk_range").c_str(), | |||
| 15079 | skillName.c_str(), skillLVL); | |||
| 15080 | snprintf(valueBuf, 127, | |||
| 15081 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_range_format").c_str(), | |||
| 15082 | attackHoverTextInfo.attackMinRange, attackHoverTextInfo.attackMaxRange); | |||
| 15083 | return true; | |||
| 15084 | case 2: | |||
| 15085 | strcpy(titleBuf, ""); | |||
| 15086 | strcpy(valueBuf, ""); | |||
| 15087 | return true; | |||
| 15088 | case 3: | |||
| 15089 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_attr_bonus_ranged").c_str()); | |||
| 15090 | snprintf(valueBuf, 127, | |||
| 15091 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15092 | attackHoverTextInfo.mainAttributeBonus); | |||
| 15093 | return true; | |||
| 15094 | case 4: | |||
| 15095 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_weapon_bonus").c_str()); | |||
| 15096 | snprintf(valueBuf, 127, | |||
| 15097 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15098 | attackHoverTextInfo.weaponBonus); | |||
| 15099 | return true; | |||
| 15100 | case 5: | |||
| 15101 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_skill_bonus").c_str()); | |||
| 15102 | snprintf(valueBuf, 127, | |||
| 15103 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15104 | attackHoverTextInfo.proficiencyBonus); | |||
| 15105 | return true; | |||
| 15106 | case 6: | |||
| 15107 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_thrown_weapon_fully_charged").c_str()); | |||
| 15108 | snprintf(valueBuf, 127, | |||
| 15109 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15110 | 3); | |||
| 15111 | return true; | |||
| 15112 | case 7: | |||
| 15113 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_thrown_weapon_base").c_str()); | |||
| 15114 | snprintf(valueBuf, 127, | |||
| 15115 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15116 | BASE_THROWN_DAMAGE); | |||
| 15117 | return true; | |||
| 15118 | default: | |||
| 15119 | return false; | |||
| 15120 | } | |||
| 15121 | } | |||
| 15122 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_THROWN_POTION ) | |||
| 15123 | { | |||
| 15124 | switch ( lineNumber ) | |||
| 15125 | { | |||
| 15126 | case 1: | |||
| 15127 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_avg").c_str()); | |||
| 15128 | snprintf(valueBuf, 127, | |||
| 15129 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_average_format").c_str(), | |||
| 15130 | (real_t)attackHoverTextInfo.attackMinRange + ((attackHoverTextInfo.attackMaxRange - attackHoverTextInfo.attackMinRange) / 2.0)); | |||
| 15131 | return true; | |||
| 15132 | case 2: | |||
| 15133 | snprintf(titleBuf, 127, Player::CharacterSheet_t::getHoverTextString("attributes_atk_range").c_str(), | |||
| 15134 | skillName.c_str(), skillLVL); | |||
| 15135 | snprintf(valueBuf, 127, | |||
| 15136 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_range_format").c_str(), | |||
| 15137 | attackHoverTextInfo.attackMinRange, attackHoverTextInfo.attackMaxRange); | |||
| 15138 | return true; | |||
| 15139 | case 3: | |||
| 15140 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_weapon_bonus").c_str()); | |||
| 15141 | snprintf(valueBuf, 127, | |||
| 15142 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15143 | attackHoverTextInfo.weaponBonus); | |||
| 15144 | return true; | |||
| 15145 | case 4: | |||
| 15146 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_skill_bonus").c_str()); | |||
| 15147 | snprintf(valueBuf, 127, | |||
| 15148 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15149 | attackHoverTextInfo.proficiencyBonus); | |||
| 15150 | return true; | |||
| 15151 | case 5: | |||
| 15152 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_thrown_weapon_base").c_str()); | |||
| 15153 | snprintf(valueBuf, 127, | |||
| 15154 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15155 | BASE_THROWN_DAMAGE); | |||
| 15156 | return true; | |||
| 15157 | default: | |||
| 15158 | return false; | |||
| 15159 | } | |||
| 15160 | } | |||
| 15161 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_WHIP ) | |||
| 15162 | { | |||
| 15163 | switch ( lineNumber ) | |||
| 15164 | { | |||
| 15165 | case 1: | |||
| 15166 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_avg").c_str()); | |||
| 15167 | snprintf(valueBuf, 127, | |||
| 15168 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_nobonus_format").c_str(), | |||
| 15169 | attackHoverTextInfo.totalAttack); | |||
| 15170 | return true; | |||
| 15171 | case 2: | |||
| 15172 | snprintf(titleBuf, 127, Player::CharacterSheet_t::getHoverTextString("attributes_atk_range").c_str(), | |||
| 15173 | skillName.c_str(), skillLVL); | |||
| 15174 | snprintf(valueBuf, 127, | |||
| 15175 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_range_format").c_str(), | |||
| 15176 | attackHoverTextInfo.attackMinRange, attackHoverTextInfo.attackMaxRange); | |||
| 15177 | return true; | |||
| 15178 | case 3: | |||
| 15179 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_attr_bonus_whip").c_str()); | |||
| 15180 | snprintf(valueBuf, 127, | |||
| 15181 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15182 | attackHoverTextInfo.mainAttributeBonus); | |||
| 15183 | return true; | |||
| 15184 | case 4: | |||
| 15185 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_weapon_bonus").c_str()); | |||
| 15186 | snprintf(valueBuf, 127, | |||
| 15187 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15188 | attackHoverTextInfo.weaponBonus); | |||
| 15189 | return true; | |||
| 15190 | case 5: | |||
| 15191 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_entry_melee_weapon_base").c_str()); | |||
| 15192 | snprintf(valueBuf, 127, | |||
| 15193 | Player::CharacterSheet_t::getHoverTextString("attributes_atk_bonus_format").c_str(), | |||
| 15194 | BASE_MELEE_DAMAGE); | |||
| 15195 | return true; | |||
| 15196 | default: | |||
| 15197 | return false; | |||
| 15198 | } | |||
| 15199 | } | |||
| 15200 | else | |||
| 15201 | { | |||
| 15202 | switch ( lineNumber ) | |||
| 15203 | { | |||
| 15204 | case 1: | |||
| 15205 | snprintf(titleBuf, 127, "%s", Player::CharacterSheet_t::getHoverTextString("attributes_atk_avg").c_str()); | |||
| 15206 | snprintf(valueBuf, 127, "-"); | |||
| 15207 | return true; | |||
| 15208 | case 2: | |||
| 15209 | strcpy(titleBuf, ""); | |||
| 15210 | strcpy(valueBuf, ""); | |||
| 15211 | return true; | |||
| 15212 | default: | |||
| 15213 | return false; | |||
| 15214 | } | |||
| 15215 | } | |||
| 15216 | return false; | |||
| 15217 | } | |||
| 15218 | ||||
| 15219 | real_t getDisplayedHPRegen(Entity* my, Stat& myStats, Uint32* outColor, char buf[32]) | |||
| 15220 | { | |||
| 15221 | real_t regen = 0.0; | |||
| 15222 | if ( outColor ) | |||
| 15223 | { | |||
| 15224 | *outColor = hudColors.characterSheetNeutral; | |||
| 15225 | } | |||
| 15226 | if ( myStats.HP > 0 ) | |||
| 15227 | { | |||
| 15228 | regen = (static_cast<real_t>(Entity::getHealthRegenInterval(my, | |||
| 15229 | myStats, true)) / TICKS_PER_SECOND50); | |||
| 15230 | if ( myStats.type == SKELETON ) | |||
| 15231 | { | |||
| 15232 | if ( !(svFlags & SV_FLAG_HUNGER) ) | |||
| 15233 | { | |||
| 15234 | regen = HEAL_TIME600 * 4 / TICKS_PER_SECOND50; | |||
| 15235 | } | |||
| 15236 | } | |||
| 15237 | if ( regen < 0 ) | |||
| 15238 | { | |||
| 15239 | regen = 0.0; | |||
| 15240 | if ( !(svFlags & SV_FLAG_HUNGER) ) | |||
| 15241 | { | |||
| 15242 | if ( outColor ) | |||
| 15243 | { | |||
| 15244 | *outColor = hudColors.characterSheetNeutral; | |||
| 15245 | } | |||
| 15246 | } | |||
| 15247 | else | |||
| 15248 | { | |||
| 15249 | if ( outColor ) | |||
| 15250 | { | |||
| 15251 | *outColor = hudColors.characterSheetRed; | |||
| 15252 | } | |||
| 15253 | } | |||
| 15254 | } | |||
| 15255 | else if ( regen < HEAL_TIME600 / TICKS_PER_SECOND50 ) | |||
| 15256 | { | |||
| 15257 | if ( outColor ) | |||
| 15258 | { | |||
| 15259 | *outColor = hudColors.characterSheetGreen; | |||
| 15260 | } | |||
| 15261 | } | |||
| 15262 | } | |||
| 15263 | else | |||
| 15264 | { | |||
| 15265 | regen = HEAL_TIME600 / TICKS_PER_SECOND50; | |||
| 15266 | } | |||
| 15267 | ||||
| 15268 | if ( regen > 0.01 ) | |||
| 15269 | { | |||
| 15270 | real_t nominalRegen = HEAL_TIME600 / TICKS_PER_SECOND50; | |||
| 15271 | regen = nominalRegen / regen; | |||
| 15272 | } | |||
| 15273 | if ( buf ) | |||
| 15274 | { | |||
| 15275 | if ( !(svFlags & SV_FLAG_HUNGER) ) | |||
| 15276 | { | |||
| 15277 | snprintf(buf, 32, "- "); | |||
| 15278 | } | |||
| 15279 | else | |||
| 15280 | { | |||
| 15281 | snprintf(buf, 32, "%.f%%", regen * 100.0); | |||
| 15282 | } | |||
| 15283 | } | |||
| 15284 | return regen * 100.0; | |||
| 15285 | } | |||
| 15286 | ||||
| 15287 | real_t getDisplayedMPRegen(Entity* my, Stat& myStats, Uint32* outColor, char buf[32]) | |||
| 15288 | { | |||
| 15289 | real_t regen = 0.0; | |||
| 15290 | bool isNegative = false; | |||
| 15291 | bool isInsectoid = false; | |||
| 15292 | if ( /*players[player.playernum]->entity*/ true ) | |||
| 15293 | { | |||
| 15294 | regen = (static_cast<real_t>(Entity::getManaRegenInterval(my, myStats, true)) / TICKS_PER_SECOND50); | |||
| 15295 | if ( myStats.type == AUTOMATON ) | |||
| 15296 | { | |||
| 15297 | if ( myStats.HUNGER <= 300 ) | |||
| 15298 | { | |||
| 15299 | isNegative = true; | |||
| 15300 | regen /= 6; // degrade faster | |||
| 15301 | } | |||
| 15302 | else if ( myStats.HUNGER > 1200 ) | |||
| 15303 | { | |||
| 15304 | if ( myStats.MP / static_cast<real_t>(std::max(1, myStats.MAXMP)) <= 0.5 ) | |||
| 15305 | { | |||
| 15306 | regen /= 4; // increase faster at < 50% mana | |||
| 15307 | } | |||
| 15308 | else | |||
| 15309 | { | |||
| 15310 | regen /= 2; // increase less faster at > 50% mana | |||
| 15311 | } | |||
| 15312 | } | |||
| 15313 | else if ( myStats.HUNGER > 300 ) | |||
| 15314 | { | |||
| 15315 | // normal manaRegenInterval 300-1200 hunger. | |||
| 15316 | } | |||
| 15317 | } | |||
| 15318 | ||||
| 15319 | if ( regen < 0.0 /*stats[player]->playerRace == RACE_INSECTOID && stats[player]->appearance == 0*/ ) | |||
| 15320 | { | |||
| 15321 | regen = 0.0; | |||
| 15322 | } | |||
| 15323 | ||||
| 15324 | if ( myStats.type == AUTOMATON ) | |||
| 15325 | { | |||
| 15326 | if ( myStats.HUNGER <= 300 ) | |||
| 15327 | { | |||
| 15328 | if ( outColor ) | |||
| 15329 | { | |||
| 15330 | *outColor = hudColors.characterSheetRed; | |||
| 15331 | } | |||
| 15332 | } | |||
| 15333 | else if ( regen < static_cast<real_t>(getBaseManaRegen(my, myStats)) / TICKS_PER_SECOND50 ) | |||
| 15334 | { | |||
| 15335 | if ( outColor ) | |||
| 15336 | { | |||
| 15337 | *outColor = hudColors.characterSheetGreen; | |||
| 15338 | } | |||
| 15339 | } | |||
| 15340 | } | |||
| 15341 | else if ( myStats.playerRace == RACE_INSECTOID && myStats.appearance == 0 ) | |||
| 15342 | { | |||
| 15343 | isInsectoid = true; | |||
| 15344 | if ( !(svFlags & SV_FLAG_HUNGER) ) | |||
| 15345 | { | |||
| 15346 | if ( outColor ) | |||
| 15347 | { | |||
| 15348 | *outColor = hudColors.characterSheetNeutral; | |||
| 15349 | } | |||
| 15350 | } | |||
| 15351 | else | |||
| 15352 | { | |||
| 15353 | if ( outColor ) | |||
| 15354 | { | |||
| 15355 | *outColor = hudColors.characterSheetRed; | |||
| 15356 | } | |||
| 15357 | } | |||
| 15358 | } | |||
| 15359 | else if ( regen < static_cast<real_t>(getBaseManaRegen(my, myStats)) / TICKS_PER_SECOND50 ) | |||
| 15360 | { | |||
| 15361 | if ( outColor ) | |||
| 15362 | { | |||
| 15363 | *outColor = hudColors.characterSheetGreen; | |||
| 15364 | } | |||
| 15365 | } | |||
| 15366 | } | |||
| 15367 | else | |||
| 15368 | { | |||
| 15369 | regen = MAGIC_REGEN_TIME300 / TICKS_PER_SECOND50; | |||
| 15370 | } | |||
| 15371 | ||||
| 15372 | if ( isNegative ) | |||
| 15373 | { | |||
| 15374 | regen *= -1; // negative | |||
| 15375 | } | |||
| 15376 | ||||
| 15377 | if ( isInsectoid ) | |||
| 15378 | { | |||
| 15379 | if ( svFlags & SV_FLAG_HUNGER ) | |||
| 15380 | { | |||
| 15381 | real_t normalRegenTime = (1000.f * 30 * 1.5) / static_cast<float>(TICKS_PER_SECOND50); // 30 base, insectoid does 1.5x in getHungerTickRate() | |||
| 15382 | normalRegenTime /= (std::max(myStats.MAXMP, 1)); // time for 1 mana in seconds | |||
| 15383 | normalRegenTime *= TICKS_PER_SECOND50; // game ticks for 1 mana | |||
| 15384 | ||||
| 15385 | regen = normalRegenTime / (regen * TICKS_PER_SECOND50); | |||
| 15386 | } | |||
| 15387 | else | |||
| 15388 | { | |||
| 15389 | if ( buf ) | |||
| 15390 | { | |||
| 15391 | snprintf(buf, 32, "-"); | |||
| 15392 | } | |||
| 15393 | return regen * 100.0; | |||
| 15394 | } | |||
| 15395 | } | |||
| 15396 | else | |||
| 15397 | { | |||
| 15398 | if ( regen > 0.01 || regen < -0.01 ) | |||
| 15399 | { | |||
| 15400 | real_t nominalRegen = MAGIC_REGEN_TIME300 / TICKS_PER_SECOND50; | |||
| 15401 | regen = nominalRegen / regen; | |||
| 15402 | } | |||
| 15403 | } | |||
| 15404 | if ( buf ) | |||
| 15405 | { | |||
| 15406 | if ( myStats.type == AUTOMATON ) | |||
| 15407 | { | |||
| 15408 | snprintf(buf, 32, Player::CharacterSheet_t::getHoverTextString("attributes_rgn_ht_small_format").c_str(), regen * 100.0); | |||
| 15409 | } | |||
| 15410 | else | |||
| 15411 | { | |||
| 15412 | snprintf(buf, 32, Player::CharacterSheet_t::getHoverTextString("attributes_rgn_small_format").c_str(), regen * 100.0); | |||
| 15413 | } | |||
| 15414 | } | |||
| 15415 | return regen * 100.0; | |||
| 15416 | } | |||
| 15417 | ||||
| 15418 | struct CharacterSheetTooltipCache_t | |||
| 15419 | { | |||
| 15420 | Sint32 baseSTR = 0; | |||
| 15421 | Sint32 baseDEX = 0; | |||
| 15422 | Sint32 baseINT = 0; | |||
| 15423 | Sint32 baseCON = 0; | |||
| 15424 | Sint32 basePER = 0; | |||
| 15425 | Sint32 baseCHR = 0; | |||
| 15426 | ||||
| 15427 | Sint32 modifiedSTR = 0; | |||
| 15428 | Sint32 modifiedDEX = 0; | |||
| 15429 | Sint32 modifiedINT = 0; | |||
| 15430 | Sint32 modifiedCON = 0; | |||
| 15431 | Sint32 modifiedPER = 0; | |||
| 15432 | Sint32 modifiedCHR = 0; | |||
| 15433 | ||||
| 15434 | Sint32 ac = 0; | |||
| 15435 | int playerRace = RACE_HUMAN; | |||
| 15436 | int playerRaceType = NOTHING; | |||
| 15437 | int type = NOTHING; | |||
| 15438 | int classnum = -1; | |||
| 15439 | bool hungerEnabled = false; | |||
| 15440 | int weapontype = 0; | |||
| 15441 | Sint32 ATK = -1; | |||
| 15442 | bool manualUpdate = false; | |||
| 15443 | ||||
| 15444 | struct TextEntries_t | |||
| 15445 | { | |||
| 15446 | std::string title = ""; | |||
| 15447 | std::string entry1 = ""; | |||
| 15448 | std::string entry2 = ""; | |||
| 15449 | std::string entry3 = ""; | |||
| 15450 | std::string entry4 = ""; | |||
| 15451 | std::string entry5 = ""; | |||
| 15452 | std::string entry6 = ""; | |||
| 15453 | std::string entry7 = ""; | |||
| 15454 | std::string entry8 = ""; | |||
| 15455 | std::string entry9 = ""; | |||
| 15456 | std::string entry10 = ""; | |||
| 15457 | std::string entry11 = ""; | |||
| 15458 | std::string entry12 = ""; | |||
| 15459 | }; | |||
| 15460 | TextEntries_t textEntries[Player::CharacterSheet_t::SHEET_ENUM_END]; | |||
| 15461 | bool needsUpdate(const int player) | |||
| 15462 | { | |||
| 15463 | if ( manualUpdate ) { return true; } | |||
| 15464 | if ( baseSTR != stats[player]->STR ) { return true; } | |||
| 15465 | if ( baseDEX != stats[player]->DEX ) { return true; } | |||
| 15466 | if ( baseCON != stats[player]->CON ) { return true; } | |||
| 15467 | if ( baseINT != stats[player]->INT ) { return true; } | |||
| 15468 | if ( basePER != stats[player]->PER ) { return true; } | |||
| 15469 | if ( baseCHR != stats[player]->CHR ) { return true; } | |||
| 15470 | ||||
| 15471 | if ( modifiedSTR != statGetSTR(stats[player], players[player]->entity) ) { return true; } | |||
| 15472 | if ( modifiedDEX != statGetDEX(stats[player], players[player]->entity) ) { return true; } | |||
| 15473 | if ( modifiedCON != statGetCON(stats[player], players[player]->entity) ) { return true; } | |||
| 15474 | if ( modifiedINT != statGetINT(stats[player], players[player]->entity) ) { return true; } | |||
| 15475 | if ( modifiedPER != statGetPER(stats[player], players[player]->entity) ) { return true; } | |||
| 15476 | if ( modifiedCHR != statGetCHR(stats[player], players[player]->entity) ) { return true; } | |||
| 15477 | ||||
| 15478 | if ( playerRace != stats[player]->playerRace ) { return true; } | |||
| 15479 | if ( hungerEnabled != (svFlags & SV_FLAG_HUNGER) ) { return true; } | |||
| 15480 | if ( ac != AC(stats[player]) ) { return true; } | |||
| 15481 | if ( weapontype != getWeaponSkill(stats[player]->weapon) ) { return true; } | |||
| 15482 | ||||
| 15483 | int playerRaceType = getMonsterFromPlayerRace(playerRace); | |||
| 15484 | int type = stats[player]->type; | |||
| 15485 | if ( arachnophobia_filter ) | |||
| 15486 | { | |||
| 15487 | if ( type == SPIDER ) | |||
| 15488 | { | |||
| 15489 | type = CRAB; | |||
| 15490 | } | |||
| 15491 | if ( playerRaceType == SPIDER ) | |||
| 15492 | { | |||
| 15493 | playerRaceType = CRAB; | |||
| 15494 | } | |||
| 15495 | } | |||
| 15496 | if ( type != this->type ) { return true; } | |||
| 15497 | if ( playerRaceType != this->playerRaceType ) { return true; } | |||
| 15498 | if ( client_classes[player] != classnum ) { return true; } | |||
| 15499 | return false; | |||
| 15500 | } | |||
| 15501 | void updateToCharacter(const int player) | |||
| 15502 | { | |||
| 15503 | manualUpdate = false; | |||
| 15504 | ||||
| 15505 | baseSTR = stats[player]->STR; | |||
| 15506 | baseDEX = stats[player]->DEX; | |||
| 15507 | baseCON = stats[player]->CON; | |||
| 15508 | baseINT = stats[player]->INT; | |||
| 15509 | basePER = stats[player]->PER; | |||
| 15510 | baseCHR = stats[player]->CHR; | |||
| 15511 | ||||
| 15512 | modifiedSTR = statGetSTR(stats[player], players[player]->entity); | |||
| 15513 | modifiedDEX = statGetDEX(stats[player], players[player]->entity); | |||
| 15514 | modifiedCON = statGetCON(stats[player], players[player]->entity); | |||
| 15515 | modifiedINT = statGetINT(stats[player], players[player]->entity); | |||
| 15516 | modifiedPER = statGetPER(stats[player], players[player]->entity); | |||
| 15517 | modifiedCHR = statGetCHR(stats[player], players[player]->entity); | |||
| 15518 | ||||
| 15519 | playerRace = stats[player]->playerRace; | |||
| 15520 | playerRaceType = getMonsterFromPlayerRace(playerRace); | |||
| 15521 | type = stats[player]->type; | |||
| 15522 | classnum = client_classes[player]; | |||
| 15523 | if ( arachnophobia_filter ) | |||
| 15524 | { | |||
| 15525 | if ( type == SPIDER ) | |||
| 15526 | { | |||
| 15527 | type = CRAB; | |||
| 15528 | } | |||
| 15529 | if ( playerRaceType == SPIDER ) | |||
| 15530 | { | |||
| 15531 | playerRaceType = CRAB; | |||
| 15532 | } | |||
| 15533 | } | |||
| 15534 | hungerEnabled = (svFlags & SV_FLAG_HUNGER); | |||
| 15535 | ac = AC(stats[player]); | |||
| 15536 | weapontype = getWeaponSkill(stats[player]->weapon); | |||
| 15537 | } | |||
| 15538 | }; | |||
| 15539 | bool blitCharacterSheetTooltipToSurf = false; | |||
| 15540 | CharacterSheetTooltipCache_t charsheetTooltipCache[MAXPLAYERS4]; | |||
| 15541 | void Player::CharacterSheet_t::updateCharacterSheetTooltip(SheetElements element, SDL_Rect pos, Player::PanelJustify_t tooltipJustify) | |||
| 15542 | { | |||
| 15543 | if ( !sheetFrame ) | |||
| 15544 | { | |||
| 15545 | return; | |||
| 15546 | } | |||
| 15547 | auto tooltipFrame = sheetFrame->findFrame("sheet tooltip"); | |||
| 15548 | if ( tooltipFrame->isDisabled() ) | |||
| 15549 | { | |||
| 15550 | tooltipOpacitySetpoint = 0; | |||
| 15551 | tooltipOpacityAnimate = 1.0; | |||
| 15552 | } | |||
| 15553 | ||||
| 15554 | if ( static_cast<int>(tooltipFrame->getOpacity()) != tooltipOpacitySetpoint ) | |||
| 15555 | { | |||
| 15556 | const real_t fpsScale = getFPSScale(144.0); | |||
| 15557 | if ( tooltipOpacitySetpoint == 0 ) | |||
| 15558 | { | |||
| 15559 | if ( ticks - tooltipDeselectedTick > 5 ) | |||
| 15560 | { | |||
| 15561 | real_t factor = 10.0; | |||
| 15562 | real_t setpointDiff = fpsScale * std::max(.05, (tooltipOpacityAnimate)) / (factor); | |||
| 15563 | tooltipOpacityAnimate -= setpointDiff; | |||
| 15564 | tooltipOpacityAnimate = std::max(0.0, tooltipOpacityAnimate); | |||
| 15565 | } | |||
| 15566 | } | |||
| 15567 | else | |||
| 15568 | { | |||
| 15569 | real_t setpointDiff = fpsScale * std::max(.05, (1.0 - tooltipOpacityAnimate)) / (1); | |||
| 15570 | tooltipOpacityAnimate += setpointDiff; | |||
| 15571 | tooltipOpacityAnimate = std::min(1.0, tooltipOpacityAnimate); | |||
| 15572 | } | |||
| 15573 | tooltipFrame->setOpacity(tooltipOpacityAnimate * 100); | |||
| 15574 | } | |||
| 15575 | else | |||
| 15576 | { | |||
| 15577 | tooltipFrame->setOpacity(tooltipOpacitySetpoint); | |||
| 15578 | } | |||
| 15579 | ||||
| 15580 | if ( selectedElement == SHEET_UNSELECTED ) | |||
| 15581 | { | |||
| 15582 | cachedElementTooltip = SHEET_UNSELECTED; | |||
| 15583 | } | |||
| 15584 | if ( player.shootmode ) | |||
| 15585 | { | |||
| 15586 | tooltipOpacitySetpoint = 0; | |||
| 15587 | tooltipOpacityAnimate = 0.0; | |||
| 15588 | } | |||
| 15589 | if ( element == SHEET_ENUM_END || element == SHEET_UNSELECTED | |||
| 15590 | || player.GUI.activeModule != Player::GUI_t::MODULE_CHARACTERSHEET ) | |||
| 15591 | { | |||
| 15592 | //tooltipFrame->setDisabled(true); | |||
| 15593 | return; | |||
| 15594 | } | |||
| 15595 | ||||
| 15596 | tooltipOpacitySetpoint = 0; | |||
| 15597 | tooltipOpacityAnimate = 1.0; | |||
| 15598 | tooltipFrame->setDisabled(false); | |||
| 15599 | tooltipFrame->setOpacity(100.0); | |||
| 15600 | tooltipDeselectedTick = ticks; | |||
| 15601 | ||||
| 15602 | //if ( keystatus[SDLK_g] ) | |||
| 15603 | //{ | |||
| 15604 | // keystatus[SDLK_g] = 0; | |||
| 15605 | // blitCharacterSheetTooltipToSurf = !blitCharacterSheetTooltipToSurf; | |||
| 15606 | // messagePlayer(0, MESSAGE_DEBUG, "%d", blitCharacterSheetTooltipToSurf); | |||
| 15607 | // if ( !blitCharacterSheetTooltipToSurf ) | |||
| 15608 | // { | |||
| 15609 | // tooltipFrame->setBlitChildren(false); | |||
| 15610 | // } | |||
| 15611 | // else if ( blitCharacterSheetTooltipToSurf ) | |||
| 15612 | // { | |||
| 15613 | // tooltipFrame->setBlitChildren(true); | |||
| 15614 | // } | |||
| 15615 | //} | |||
| 15616 | ||||
| 15617 | bool redraw = false; | |||
| 15618 | if ( cachedElementTooltip != selectedElement | |||
| 15619 | || cachedElementTooltip == SHEET_ENUM_END || cachedElementTooltip == SHEET_UNSELECTED | |||
| 15620 | || charsheetTooltipCache[player.playernum].needsUpdate(player.playernum) ) | |||
| 15621 | { | |||
| 15622 | redraw = true; | |||
| 15623 | cachedElementTooltip = selectedElement; | |||
| 15624 | charsheetTooltipCache[player.playernum].updateToCharacter(player.playernum); | |||
| 15625 | } | |||
| 15626 | ||||
| 15627 | if ( !redraw ) | |||
| 15628 | { | |||
| 15629 | return; | |||
| 15630 | } | |||
| 15631 | ||||
| 15632 | ||||
| 15633 | Uint32 defaultColor = hudColors.characterSheetNeutral; | |||
| 15634 | auto txt = tooltipFrame->findField("tooltip text"); | |||
| 15635 | txt->setColor(defaultColor); | |||
| 15636 | auto txtRightAlignHint = tooltipFrame->findField("tooltip text right align hint"); | |||
| 15637 | txtRightAlignHint->setColor(hudColors.characterSheetFaintText); | |||
| 15638 | txtRightAlignHint->setDisabled(true); | |||
| 15639 | ||||
| 15640 | for ( int i = 1; i <= NUM_CHARSHEET_TOOLTIP_TEXT_FIELDS; ++i ) | |||
| 15641 | { | |||
| 15642 | char glyphName[32] = ""; | |||
| 15643 | snprintf(glyphName, sizeof(glyphName), "glyph %d", i); | |||
| 15644 | if ( auto glyph = tooltipFrame->findImage(glyphName) ) | |||
| 15645 | { | |||
| 15646 | glyph->disabled = true; | |||
| 15647 | } | |||
| 15648 | ||||
| 15649 | auto entry = characterSheetTooltipTextFields[player.playernum][i]; assert(entry)(static_cast<void> (0)); | |||
| 15650 | entry->setDisabled(true); | |||
| 15651 | entry->setHJustify(Frame::justify_t::LEFT); | |||
| 15652 | entry->setVJustify(Field::justify_t::CENTER); | |||
| 15653 | entry->setColor(defaultColor); | |||
| 15654 | } | |||
| 15655 | auto div = tooltipFrame->findImage("tooltip divider 1"); | |||
| 15656 | div->disabled = true; | |||
| 15657 | auto div2 = tooltipFrame->findImage("tooltip divider 2"); | |||
| 15658 | div2->disabled = true; | |||
| 15659 | ||||
| 15660 | for ( int i = 1; i <= NUM_CHARSHEET_TOOLTIP_BACKING_FRAMES; ++i ) | |||
| 15661 | { | |||
| 15662 | auto txtValueBackingFrame = characterSheetTooltipTextBackingFrames[player.playernum][i]; | |||
| 15663 | txtValueBackingFrame->setDisabled(true); | |||
| 15664 | } | |||
| 15665 | ||||
| 15666 | auto raceTooltip = tooltipFrame->findFrame("sheet race tooltip"); | |||
| 15667 | raceTooltip->setDisabled(true); | |||
| 15668 | auto classTooltip = tooltipFrame->findFrame("sheet class tooltip"); | |||
| 15669 | classTooltip->setDisabled(true); | |||
| 15670 | ||||
| 15671 | if ( !(element >= Player::CharacterSheet_t::SHEET_STR && element <= Player::CharacterSheet_t::SHEET_CHR) ) | |||
| 15672 | { | |||
| 15673 | auto tooltipTopLeft = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 15674 | tooltipTopLeft->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TL_00.png"; | |||
| 15675 | auto tooltipTop = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 15676 | tooltipTop->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_T_00.png"; | |||
| 15677 | auto tooltipTopRight = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 15678 | tooltipTopRight->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TR_00.png"; | |||
| 15679 | imageSetWidthHeight9x9(tooltipFrame, skillsheetEffectBackgroundImages); | |||
| 15680 | } | |||
| 15681 | ||||
| 15682 | if ( element >= Player::CharacterSheet_t::SHEET_STR && element <= Player::CharacterSheet_t::SHEET_CHR ) | |||
| 15683 | { | |||
| 15684 | auto tooltipTopLeft = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 15685 | tooltipTopLeft->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TL_Blue_00.png"; | |||
| 15686 | auto tooltipTop = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 15687 | tooltipTop->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_T_Blue_00.png"; | |||
| 15688 | auto tooltipTopRight = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 15689 | tooltipTopRight->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TR_Blue_00.png"; | |||
| 15690 | imageSetWidthHeight9x9(tooltipFrame, skillsheetEffectBackgroundImages); | |||
| 15691 | ||||
| 15692 | int maxWidth = 260; | |||
| 15693 | if ( getHoverTextString("stat_max_tooltip_width") != defaultString ) | |||
| 15694 | { | |||
| 15695 | maxWidth = std::max(0, std::stoi(getHoverTextString("stat_max_tooltip_width"))); | |||
| 15696 | } | |||
| 15697 | int minWidth = 0; | |||
| 15698 | if ( getHoverTextString("stat_min_tooltip_width") != defaultString ) | |||
| 15699 | { | |||
| 15700 | minWidth = std::max(0, std::stoi(getHoverTextString("stat_min_tooltip_width"))); | |||
| 15701 | } | |||
| 15702 | const int padx = 16; | |||
| 15703 | const int pady1 = 8; | |||
| 15704 | const int pady2 = 4; | |||
| 15705 | const int padxMid = 4; | |||
| 15706 | const int padyMid = 8; | |||
| 15707 | SDL_Rect tooltipPos = SDL_Rect{ 400, 0, maxWidth, 100 }; | |||
| 15708 | ||||
| 15709 | std::string titleText = ""; | |||
| 15710 | std::string descText = ""; | |||
| 15711 | int value = 0; | |||
| 15712 | switch ( element ) | |||
| 15713 | { | |||
| 15714 | case SHEET_STR: | |||
| 15715 | titleText = getHoverTextString("stat_str_title"); | |||
| 15716 | descText = getHoverTextString("stat_str_desc"); | |||
| 15717 | break; | |||
| 15718 | case SHEET_DEX: | |||
| 15719 | titleText = getHoverTextString("stat_dex_title"); | |||
| 15720 | descText = getHoverTextString("stat_dex_desc"); | |||
| 15721 | break; | |||
| 15722 | case SHEET_CON: | |||
| 15723 | titleText = getHoverTextString("stat_con_title"); | |||
| 15724 | descText = getHoverTextString("stat_con_desc"); | |||
| 15725 | break; | |||
| 15726 | case SHEET_INT: | |||
| 15727 | titleText = getHoverTextString("stat_int_title"); | |||
| 15728 | descText = getHoverTextString("stat_int_desc"); | |||
| 15729 | break; | |||
| 15730 | case SHEET_PER: | |||
| 15731 | titleText = getHoverTextString("stat_per_title"); | |||
| 15732 | descText = getHoverTextString("stat_per_desc"); | |||
| 15733 | break; | |||
| 15734 | case SHEET_CHR: | |||
| 15735 | titleText = getHoverTextString("stat_chr_title"); | |||
| 15736 | descText = getHoverTextString("stat_chr_desc"); | |||
| 15737 | break; | |||
| 15738 | default: | |||
| 15739 | break; | |||
| 15740 | } | |||
| 15741 | ||||
| 15742 | txt->setText(titleText.c_str()); | |||
| 15743 | SDL_Rect txtPos = SDL_Rect{ padx, pady1 - 2, maxWidth - padx * 2, 80 }; | |||
| 15744 | txt->setSize(txtPos); | |||
| 15745 | if ( charsheetTooltipCache[player.playernum].textEntries[element].title != txt->getText() ) | |||
| 15746 | { | |||
| 15747 | txt->reflowTextToFit(0); | |||
| 15748 | charsheetTooltipCache[player.playernum].textEntries[element].title = txt->getText(); | |||
| 15749 | } | |||
| 15750 | txt->setColor(hudColors.characterSheetHeadingText); | |||
| 15751 | Font* actualFont = Font::get(txt->getFont()); | |||
| 15752 | int txtHeight = txt->getNumTextLines() * actualFont->height(true); | |||
| 15753 | txtPos.h = txtHeight + 4; | |||
| 15754 | auto txtGet = Text::get(txt->getLongestLine().c_str(), txt->getFont(), | |||
| 15755 | txt->getTextColor(), txt->getOutlineColor()); | |||
| 15756 | txtPos.w = txtGet->getWidth(); | |||
| 15757 | txtPos.w = std::max(minWidth - padx * 2, txtPos.w); | |||
| 15758 | txt->setSize(txtPos); | |||
| 15759 | ||||
| 15760 | tooltipPos.w = (txtPos.w + padx * 2); | |||
| 15761 | ||||
| 15762 | unsigned int longestValue = 0; | |||
| 15763 | std::map<int, std::pair<Field*, SDL_Rect>> valueSizes; | |||
| 15764 | ||||
| 15765 | int currentHeight = txtPos.y + (actualFont->height(true) * 1) + 2; | |||
| 15766 | const int extraTextHeightForLowerCharacters = 4; | |||
| 15767 | { | |||
| 15768 | currentHeight += padyMid; | |||
| 15769 | auto entry = characterSheetTooltipTextFields[player.playernum][1]; assert(entry)(static_cast<void> (0)); | |||
| 15770 | entry->setDisabled(false); | |||
| 15771 | char buf[128] = ""; | |||
| 15772 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_base_amount").c_str()); | |||
| 15773 | entry->setText(buf); | |||
| 15774 | entry->setVJustify(Field::justify_t::TOP); | |||
| 15775 | ||||
| 15776 | auto glyphBacking = tooltipFrame->findImage("glyph 1"); | |||
| 15777 | glyphBacking->disabled = false; | |||
| 15778 | glyphBacking->path = getHoverTextString("icon_backing_path"); | |||
| 15779 | glyphBacking->pos.x = padx + padxMid + 4; | |||
| 15780 | glyphBacking->pos.y = currentHeight + 6; | |||
| 15781 | glyphBacking->pos.w = 44; | |||
| 15782 | glyphBacking->pos.h = 44; | |||
| 15783 | ||||
| 15784 | auto glyphIcon = tooltipFrame->findImage("glyph 2"); | |||
| 15785 | glyphIcon->disabled = false; | |||
| 15786 | glyphIcon->path = ""; | |||
| 15787 | switch ( element ) | |||
| 15788 | { | |||
| 15789 | case SHEET_STR: | |||
| 15790 | glyphIcon->path = getHoverTextString("icon_str_path"); | |||
| 15791 | break; | |||
| 15792 | case SHEET_DEX: | |||
| 15793 | glyphIcon->path = getHoverTextString("icon_dex_path"); | |||
| 15794 | break; | |||
| 15795 | case SHEET_CON: | |||
| 15796 | glyphIcon->path = getHoverTextString("icon_con_path"); | |||
| 15797 | break; | |||
| 15798 | case SHEET_INT: | |||
| 15799 | glyphIcon->path = getHoverTextString("icon_int_path"); | |||
| 15800 | break; | |||
| 15801 | case SHEET_PER: | |||
| 15802 | glyphIcon->path = getHoverTextString("icon_per_path"); | |||
| 15803 | break; | |||
| 15804 | case SHEET_CHR: | |||
| 15805 | glyphIcon->path = getHoverTextString("icon_chr_path"); | |||
| 15806 | break; | |||
| 15807 | default: | |||
| 15808 | break; | |||
| 15809 | } | |||
| 15810 | glyphIcon->pos.w = 24; | |||
| 15811 | glyphIcon->pos.h = 24; | |||
| 15812 | glyphIcon->pos.x = glyphBacking->pos.x + glyphBacking->pos.w / 2 - glyphIcon->pos.w / 2; | |||
| 15813 | glyphIcon->pos.y = glyphBacking->pos.y + glyphBacking->pos.h / 2 - glyphIcon->pos.h / 2; | |||
| 15814 | ||||
| 15815 | SDL_Rect entryPos = entry->getSize(); | |||
| 15816 | entryPos.x = padx / 2 + glyphBacking->pos.x + glyphBacking->pos.w; | |||
| 15817 | entryPos.y = currentHeight; | |||
| 15818 | entryPos.w = txtPos.w - (padxMid + glyphBacking->pos.x + glyphBacking->pos.w); | |||
| 15819 | entry->setSize(entryPos); | |||
| 15820 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry1 != entry->getText() ) | |||
| 15821 | { | |||
| 15822 | entry->reflowTextToFit(0); | |||
| 15823 | charsheetTooltipCache[player.playernum].textEntries[element].entry1 = entry->getText(); | |||
| 15824 | } | |||
| 15825 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 15826 | entry->setSize(entryPos); | |||
| 15827 | entry->setColor(defaultColor); | |||
| 15828 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 15829 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 15830 | ||||
| 15831 | auto entryValue = characterSheetTooltipTextFields[player.playernum][2]; assert(entry)(static_cast<void> (0)); | |||
| 15832 | entryValue->setDisabled(false); | |||
| 15833 | int value = 0; | |||
| 15834 | char valueBuf[128] = ""; | |||
| 15835 | switch ( element ) | |||
| 15836 | { | |||
| 15837 | case SHEET_STR: | |||
| 15838 | value = stats[player.playernum]->STR; | |||
| 15839 | snprintf(valueBuf, sizeof(valueBuf), "%d STR", value); | |||
| 15840 | break; | |||
| 15841 | case SHEET_DEX: | |||
| 15842 | value = stats[player.playernum]->DEX; | |||
| 15843 | snprintf(valueBuf, sizeof(valueBuf), "%d DEX", value); | |||
| 15844 | break; | |||
| 15845 | case SHEET_CON: | |||
| 15846 | value = stats[player.playernum]->CON; | |||
| 15847 | snprintf(valueBuf, sizeof(valueBuf), "%d CON", value); | |||
| 15848 | break; | |||
| 15849 | case SHEET_INT: | |||
| 15850 | value = stats[player.playernum]->INT; | |||
| 15851 | snprintf(valueBuf, sizeof(valueBuf), "%d INT", value); | |||
| 15852 | break; | |||
| 15853 | case SHEET_PER: | |||
| 15854 | value = stats[player.playernum]->PER; | |||
| 15855 | snprintf(valueBuf, sizeof(valueBuf), "%d PER", value); | |||
| 15856 | break; | |||
| 15857 | case SHEET_CHR: | |||
| 15858 | value = stats[player.playernum]->CHR; | |||
| 15859 | snprintf(valueBuf, sizeof(valueBuf), "%d CHR", value); | |||
| 15860 | break; | |||
| 15861 | default: | |||
| 15862 | break; | |||
| 15863 | } | |||
| 15864 | entryValue->setColor(hudColors.characterSheetNeutral); | |||
| 15865 | if ( value < 0 ) | |||
| 15866 | { | |||
| 15867 | entryValue->setColor(hudColors.characterSheetRed); | |||
| 15868 | } | |||
| 15869 | entryValue->setText(valueBuf); | |||
| 15870 | SDL_Rect entryValuePos = entry->getSize(); | |||
| 15871 | entryValue->setSize(entryValuePos); | |||
| 15872 | entryValue->setHJustify(Frame::justify_t::RIGHT); | |||
| 15873 | entryValue->setVJustify(Field::justify_t::TOP); | |||
| 15874 | ||||
| 15875 | /*auto txtValueBackingFrame = tooltipFrame->findFrame("txt value backing frame 1"); | |||
| 15876 | SDL_Rect backingFramePos = entryValue->getSize(); | |||
| 15877 | auto txtValueGet = Text::get(entryValue->getText(), entryValue->getFont(), | |||
| 15878 | entryValue->getTextColor(), entryValue->getOutlineColor()); | |||
| 15879 | longestValue = std::max(longestValue, txtValueGet->getWidth()); | |||
| 15880 | backingFramePos.x = backingFramePos.x + backingFramePos.w; | |||
| 15881 | backingFramePos.h = actualFont->height(true) + extraTextHeightForLowerCharacters - 2; | |||
| 15882 | valueSizes[1] = std::make_pair(entryValue, backingFramePos); | |||
| 15883 | txtValueBackingFrame->setDisabled(false);*/ | |||
| 15884 | } | |||
| 15885 | { | |||
| 15886 | currentHeight += 0;// padyMid / 2; | |||
| 15887 | auto entry = characterSheetTooltipTextFields[player.playernum][3]; assert(entry)(static_cast<void> (0)); | |||
| 15888 | entry->setDisabled(false); | |||
| 15889 | char buf[128] = ""; | |||
| 15890 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_modified_amount").c_str()); | |||
| 15891 | entry->setText(buf); | |||
| 15892 | entry->setVJustify(Field::justify_t::TOP); | |||
| 15893 | ||||
| 15894 | auto glyphBacking = tooltipFrame->findImage("glyph 1"); | |||
| 15895 | ||||
| 15896 | SDL_Rect entryPos = entry->getSize(); | |||
| 15897 | entryPos.x = padx / 2 + glyphBacking->pos.x + glyphBacking->pos.w; | |||
| 15898 | entryPos.y = currentHeight; | |||
| 15899 | entryPos.w = txtPos.w - (padxMid + glyphBacking->pos.x + glyphBacking->pos.w); | |||
| 15900 | entry->setSize(entryPos); | |||
| 15901 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry3 != entry->getText() ) | |||
| 15902 | { | |||
| 15903 | entry->reflowTextToFit(0); | |||
| 15904 | charsheetTooltipCache[player.playernum].textEntries[element].entry3 = entry->getText(); | |||
| 15905 | } | |||
| 15906 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 15907 | entry->setSize(entryPos); | |||
| 15908 | entry->setColor(defaultColor); | |||
| 15909 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 15910 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 15911 | ||||
| 15912 | auto entryValue = characterSheetTooltipTextFields[player.playernum][4]; assert(entry)(static_cast<void> (0)); | |||
| 15913 | entryValue->setDisabled(false); | |||
| 15914 | char valueBuf[128] = ""; | |||
| 15915 | int value = 0; | |||
| 15916 | switch ( element ) | |||
| 15917 | { | |||
| 15918 | case SHEET_STR: | |||
| 15919 | value = statGetSTR(stats[player.playernum], players[player.playernum]->entity); | |||
| 15920 | value -= stats[player.playernum]->STR; | |||
| 15921 | snprintf(valueBuf, sizeof(valueBuf), "%+d STR", value); | |||
| 15922 | break; | |||
| 15923 | case SHEET_DEX: | |||
| 15924 | value = statGetDEX(stats[player.playernum], players[player.playernum]->entity); | |||
| 15925 | value -= stats[player.playernum]->DEX; | |||
| 15926 | snprintf(valueBuf, sizeof(valueBuf), "%+d DEX", value); | |||
| 15927 | break; | |||
| 15928 | case SHEET_CON: | |||
| 15929 | value = statGetCON(stats[player.playernum], players[player.playernum]->entity); | |||
| 15930 | value -= stats[player.playernum]->CON; | |||
| 15931 | snprintf(valueBuf, sizeof(valueBuf), "%+d CON", value); | |||
| 15932 | break; | |||
| 15933 | case SHEET_INT: | |||
| 15934 | value = statGetINT(stats[player.playernum], players[player.playernum]->entity); | |||
| 15935 | value -= stats[player.playernum]->INT; | |||
| 15936 | snprintf(valueBuf, sizeof(valueBuf), "%+d INT", value); | |||
| 15937 | break; | |||
| 15938 | case SHEET_PER: | |||
| 15939 | value = statGetPER(stats[player.playernum], players[player.playernum]->entity); | |||
| 15940 | value -= stats[player.playernum]->PER; | |||
| 15941 | snprintf(valueBuf, sizeof(valueBuf), "%+d PER", value); | |||
| 15942 | break; | |||
| 15943 | case SHEET_CHR: | |||
| 15944 | value = statGetCHR(stats[player.playernum], players[player.playernum]->entity); | |||
| 15945 | value -= stats[player.playernum]->CHR; | |||
| 15946 | snprintf(valueBuf, sizeof(valueBuf), "%+d CHR", value); | |||
| 15947 | break; | |||
| 15948 | default: | |||
| 15949 | break; | |||
| 15950 | } | |||
| 15951 | entryValue->setColor(hudColors.characterSheetNeutral); | |||
| 15952 | if ( value < 0 ) | |||
| 15953 | { | |||
| 15954 | entryValue->setColor(hudColors.characterSheetRed); | |||
| 15955 | } | |||
| 15956 | else if ( value > 0 ) | |||
| 15957 | { | |||
| 15958 | entryValue->setColor(hudColors.characterSheetGreen); | |||
| 15959 | } | |||
| 15960 | entryValue->setText(valueBuf); | |||
| 15961 | SDL_Rect entryValuePos = entry->getSize(); | |||
| 15962 | entryValue->setSize(entryValuePos); | |||
| 15963 | entryValue->setHJustify(Frame::justify_t::RIGHT); | |||
| 15964 | entryValue->setVJustify(Field::justify_t::TOP); | |||
| 15965 | ||||
| 15966 | /*auto txtValueBackingFrame = tooltipFrame->findFrame("txt value backing frame 2"); | |||
| 15967 | SDL_Rect backingFramePos = entryValue->getSize(); | |||
| 15968 | auto txtValueGet = Text::get(entryValue->getText(), entryValue->getFont(), | |||
| 15969 | entryValue->getTextColor(), entryValue->getOutlineColor()); | |||
| 15970 | longestValue = std::max(longestValue, txtValueGet->getWidth()); | |||
| 15971 | backingFramePos.x = backingFramePos.x + backingFramePos.w; | |||
| 15972 | backingFramePos.h = actualFont->height(true) + extraTextHeightForLowerCharacters - 2; | |||
| 15973 | valueSizes[2] = std::make_pair(entryValue, backingFramePos); | |||
| 15974 | txtValueBackingFrame->setDisabled(false);*/ | |||
| 15975 | } | |||
| 15976 | { | |||
| 15977 | // stat extra number display | |||
| 15978 | currentHeight += padyMid; | |||
| 15979 | auto entry = characterSheetTooltipTextFields[player.playernum][5]; assert(entry)(static_cast<void> (0)); | |||
| 15980 | entry->setDisabled(false); | |||
| 15981 | char buf[128] = ""; | |||
| 15982 | if ( element == SHEET_STR ) | |||
| 15983 | { | |||
| 15984 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_str_atk_bonus").c_str()); | |||
| 15985 | } | |||
| 15986 | else if ( element == SHEET_DEX ) | |||
| 15987 | { | |||
| 15988 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_dex_ranged_atk_bonus").c_str()); | |||
| 15989 | } | |||
| 15990 | else if ( element == SHEET_CON ) | |||
| 15991 | { | |||
| 15992 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_con_ac_bonus").c_str()); | |||
| 15993 | } | |||
| 15994 | else if ( element == SHEET_PER ) | |||
| 15995 | { | |||
| 15996 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_per_pierce_bonus").c_str()); | |||
| 15997 | } | |||
| 15998 | else if ( element == SHEET_INT ) | |||
| 15999 | { | |||
| 16000 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_int_pwr_bonus").c_str()); | |||
| 16001 | } | |||
| 16002 | else if ( element == SHEET_CHR ) | |||
| 16003 | { | |||
| 16004 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_chr_buying_bonus").c_str()); | |||
| 16005 | } | |||
| 16006 | entry->setText(buf); | |||
| 16007 | entry->setVJustify(Field::justify_t::TOP); | |||
| 16008 | ||||
| 16009 | SDL_Rect entryPos = entry->getSize(); | |||
| 16010 | entryPos.x = padx + padxMid; | |||
| 16011 | entryPos.y = currentHeight; | |||
| 16012 | entryPos.w = txtPos.w - (padxMid * 2); | |||
| 16013 | entry->setSize(entryPos); | |||
| 16014 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry5 != entry->getText() ) | |||
| 16015 | { | |||
| 16016 | entry->reflowTextToFit(0); | |||
| 16017 | charsheetTooltipCache[player.playernum].textEntries[element].entry5 = entry->getText(); | |||
| 16018 | } | |||
| 16019 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 16020 | entry->setSize(entryPos); | |||
| 16021 | entry->setColor(defaultColor); | |||
| 16022 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 16023 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 16024 | ||||
| 16025 | auto entryValue = characterSheetTooltipTextFields[player.playernum][6]; assert(entry)(static_cast<void> (0)); | |||
| 16026 | entryValue->setDisabled(false); | |||
| 16027 | char valueBuf[128] = ""; | |||
| 16028 | int value = 0; | |||
| 16029 | switch ( element ) | |||
| 16030 | { | |||
| 16031 | case SHEET_STR: | |||
| 16032 | { | |||
| 16033 | Sint32 STR = statGetSTR(stats[player.playernum], players[player.playernum]->entity); | |||
| 16034 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("stat_atk_value_format").c_str(), STR); | |||
| 16035 | } | |||
| 16036 | break; | |||
| 16037 | case SHEET_DEX: | |||
| 16038 | { | |||
| 16039 | Sint32 DEX = statGetDEX(stats[player.playernum], players[player.playernum]->entity); | |||
| 16040 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("stat_atk_value_format").c_str(), DEX); | |||
| 16041 | } | |||
| 16042 | break; | |||
| 16043 | case SHEET_CON: | |||
| 16044 | { | |||
| 16045 | Sint32 CON = statGetCON(stats[player.playernum], players[player.playernum]->entity); | |||
| 16046 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("stat_ac_value_format").c_str(), CON); | |||
| 16047 | } | |||
| 16048 | break; | |||
| 16049 | case SHEET_INT: | |||
| 16050 | { | |||
| 16051 | //real_t val = getBonusFromCasterOfSpellElement(players[player.playernum]->entity, stats[player.playernum], nullptr, SPELL_NONE) * 100.0; | |||
| 16052 | int INT = statGetINT(stats[player.playernum], players[player.playernum]->entity); | |||
| 16053 | real_t bonus = 0.0; | |||
| 16054 | if ( INT > 0 ) | |||
| 16055 | { | |||
| 16056 | bonus += INT / 100.0; | |||
| 16057 | } | |||
| 16058 | real_t val = bonus * 100.0; | |||
| 16059 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("stat_pwr_value_format").c_str(), val); | |||
| 16060 | } | |||
| 16061 | break; | |||
| 16062 | case SHEET_PER: | |||
| 16063 | { | |||
| 16064 | real_t val = std::min(std::max(statGetPER(stats[player.playernum], players[player.playernum]->entity) / 2, 0), 50); | |||
| 16065 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("stat_pierce_value_format").c_str(), val); | |||
| 16066 | } | |||
| 16067 | break; | |||
| 16068 | case SHEET_CHR: | |||
| 16069 | { | |||
| 16070 | real_t val = 1 / ((50 + stats[player.playernum]->getModifiedProficiency(PRO_TRADING)) / 150.f); // buy value | |||
| 16071 | real_t normalVal = val; | |||
| 16072 | //normalVal /= (1.f + statGetCHR(stats[player.playernum], players[player.playernum]->entity) / 20.f); | |||
| 16073 | normalVal = std::max(1.0, normalVal); | |||
| 16074 | ||||
| 16075 | int stat = stats[player.playernum]->CHR; | |||
| 16076 | stats[player.playernum]->CHR = 0; | |||
| 16077 | stats[player.playernum]->CHR -= statGetCHR(stats[player.playernum], players[player.playernum]->entity); | |||
| 16078 | real_t zeroVal = val; | |||
| 16079 | //zeroVal /= (1.f + statGetCHR(stats[player.playernum], players[player.playernum]->entity) / 20.f); | |||
| 16080 | zeroVal = std::max(1.0, zeroVal); | |||
| 16081 | stats[player.playernum]->CHR = stat; | |||
| 16082 | ||||
| 16083 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("stat_buying_value_format").c_str(), (zeroVal - normalVal) * 100.0); | |||
| 16084 | } | |||
| 16085 | break; | |||
| 16086 | default: | |||
| 16087 | break; | |||
| 16088 | } | |||
| 16089 | entryValue->setColor(hudColors.characterSheetNeutral); | |||
| 16090 | if ( value < 0 ) | |||
| 16091 | { | |||
| 16092 | entryValue->setColor(hudColors.characterSheetRed); | |||
| 16093 | } | |||
| 16094 | else if ( value > 0 ) | |||
| 16095 | { | |||
| 16096 | entryValue->setColor(hudColors.characterSheetGreen); | |||
| 16097 | } | |||
| 16098 | entryValue->setText(valueBuf); | |||
| 16099 | entryValue->setSize(entry->getSize()); | |||
| 16100 | entryValue->setHJustify(Frame::justify_t::LEFT); | |||
| 16101 | entryValue->setVJustify(Field::justify_t::TOP); | |||
| 16102 | ||||
| 16103 | auto txtValueBackingFrame = characterSheetTooltipTextBackingFrames[player.playernum][3]; | |||
| 16104 | SDL_Rect backingFramePos = entryValue->getSize(); | |||
| 16105 | auto txtValueGet = Text::get(entryValue->getText(), entryValue->getFont(), | |||
| 16106 | entryValue->getTextColor(), entryValue->getOutlineColor()); | |||
| 16107 | longestValue = std::max(longestValue, txtValueGet->getWidth()); | |||
| 16108 | backingFramePos.x = backingFramePos.x + backingFramePos.w; | |||
| 16109 | backingFramePos.h = actualFont->height(true) + extraTextHeightForLowerCharacters - 2; | |||
| 16110 | valueSizes[3] = std::make_pair(entryValue, backingFramePos); | |||
| 16111 | txtValueBackingFrame->setDisabled(false); | |||
| 16112 | } | |||
| 16113 | if ( element == SHEET_STR || element == SHEET_DEX || element == SHEET_INT || element == SHEET_PER || element == SHEET_CHR ) | |||
| 16114 | { | |||
| 16115 | // stat extra number display | |||
| 16116 | currentHeight += padyMid; | |||
| 16117 | auto entry = characterSheetTooltipTextFields[player.playernum][7]; assert(entry)(static_cast<void> (0)); | |||
| 16118 | entry->setDisabled(false); | |||
| 16119 | char buf[128] = ""; | |||
| 16120 | ||||
| 16121 | if ( element == SHEET_STR ) | |||
| 16122 | { | |||
| 16123 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_str_movement_bonus").c_str()); | |||
| 16124 | } | |||
| 16125 | else if ( element == SHEET_DEX ) | |||
| 16126 | { | |||
| 16127 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_dex_thrown_atk_bonus").c_str()); | |||
| 16128 | } | |||
| 16129 | else if ( element == SHEET_INT ) | |||
| 16130 | { | |||
| 16131 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_int_mp_regen_bonus").c_str()); | |||
| 16132 | } | |||
| 16133 | else if ( element == SHEET_PER ) | |||
| 16134 | { | |||
| 16135 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_per_light_bonus").c_str()); | |||
| 16136 | } | |||
| 16137 | else if ( element == SHEET_CHR ) | |||
| 16138 | { | |||
| 16139 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_chr_selling_bonus").c_str()); | |||
| 16140 | } | |||
| 16141 | entry->setText(buf); | |||
| 16142 | entry->setVJustify(Field::justify_t::TOP); | |||
| 16143 | ||||
| 16144 | SDL_Rect entryPos = entry->getSize(); | |||
| 16145 | entryPos.x = padx + padxMid; | |||
| 16146 | entryPos.y = currentHeight; | |||
| 16147 | entryPos.w = txtPos.w - (padxMid * 2); | |||
| 16148 | entry->setSize(entryPos); | |||
| 16149 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry7 != entry->getText() ) | |||
| 16150 | { | |||
| 16151 | entry->reflowTextToFit(0); | |||
| 16152 | charsheetTooltipCache[player.playernum].textEntries[element].entry7 = entry->getText(); | |||
| 16153 | } | |||
| 16154 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 16155 | entry->setSize(entryPos); | |||
| 16156 | entry->setColor(defaultColor); | |||
| 16157 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 16158 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 16159 | ||||
| 16160 | auto entryValue = characterSheetTooltipTextFields[player.playernum][8]; assert(entry)(static_cast<void> (0)); | |||
| 16161 | entryValue->setDisabled(false); | |||
| 16162 | char valueBuf[128] = ""; | |||
| 16163 | int value = 0; | |||
| 16164 | switch ( element ) | |||
| 16165 | { | |||
| 16166 | case SHEET_STR: | |||
| 16167 | { | |||
| 16168 | Sint32 STR = statGetSTR(stats[player.playernum], players[player.playernum]->entity); | |||
| 16169 | Sint32 DEX = statGetDEX(stats[player.playernum], players[player.playernum]->entity); | |||
| 16170 | real_t weightratio1 = player.movement.getWeightRatio(player.movement.getCharacterModifiedWeight(), 0); | |||
| 16171 | real_t weightratio2 = player.movement.getWeightRatio(player.movement.getCharacterModifiedWeight(), STR); | |||
| 16172 | real_t speedFactor1 = player.movement.getSpeedFactor(weightratio1, DEX); | |||
| 16173 | real_t speedFactor2 = player.movement.getSpeedFactor(weightratio2, DEX); | |||
| 16174 | real_t maxSpeed = player.movement.getMaximumSpeed(); | |||
| 16175 | ||||
| 16176 | real_t noSTRPercent = 100.0 * speedFactor1 / std::fmax(.01, maxSpeed); | |||
| 16177 | real_t currentPercent = 100.0 * speedFactor2 / std::fmax(.01, maxSpeed); | |||
| 16178 | real_t displayValue = currentPercent - noSTRPercent; | |||
| 16179 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("stat_movement_value_format").c_str(), displayValue); | |||
| 16180 | } | |||
| 16181 | break; | |||
| 16182 | case SHEET_DEX: | |||
| 16183 | { | |||
| 16184 | Sint32 DEX = statGetDEX(stats[player.playernum], players[player.playernum]->entity); | |||
| 16185 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("stat_atk_value_format").c_str(), DEX / 4); | |||
| 16186 | } | |||
| 16187 | break; | |||
| 16188 | case SHEET_CON: | |||
| 16189 | break; | |||
| 16190 | case SHEET_INT: | |||
| 16191 | { | |||
| 16192 | Sint32 oldINT = stats[player.playernum]->INT; | |||
| 16193 | stats[player.playernum]->INT += -statGetINT(stats[player.playernum], player.entity); | |||
| 16194 | real_t regenWithoutINT = getDisplayedMPRegen(player.entity, *stats[player.playernum], nullptr, nullptr); | |||
| 16195 | stats[player.playernum]->INT = oldINT; | |||
| 16196 | ||||
| 16197 | real_t regenTotal = getDisplayedMPRegen(player.entity, *stats[player.playernum], nullptr, nullptr); | |||
| 16198 | real_t regenStatSkill = regenTotal - regenWithoutINT; | |||
| 16199 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("stat_mp_regen_value_format").c_str(), regenStatSkill); | |||
| 16200 | } | |||
| 16201 | break; | |||
| 16202 | case SHEET_PER: | |||
| 16203 | { | |||
| 16204 | const int PER = statGetPER(stats[player.playernum], players[player.playernum]->entity); | |||
| 16205 | const int range_bonus = std::min(std::max(0, PER / 5), 2); | |||
| 16206 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("stat_light_value_format").c_str(), range_bonus); | |||
| 16207 | } | |||
| 16208 | break; | |||
| 16209 | case SHEET_CHR: | |||
| 16210 | { | |||
| 16211 | real_t val = (50 + stats[player.playernum]->getModifiedProficiency(PRO_TRADING)) / 150.f; // sell value | |||
| 16212 | real_t normalVal = val; | |||
| 16213 | normalVal *= (1.f + statGetCHR(stats[player.playernum], players[player.playernum]->entity) / 20.f); | |||
| 16214 | normalVal = std::min(1.0, normalVal); | |||
| 16215 | ||||
| 16216 | int stat = stats[player.playernum]->CHR; | |||
| 16217 | stats[player.playernum]->CHR = 0; | |||
| 16218 | stats[player.playernum]->CHR -= statGetCHR(stats[player.playernum], players[player.playernum]->entity); | |||
| 16219 | real_t zeroVal = val; | |||
| 16220 | zeroVal *= (1.f + statGetCHR(stats[player.playernum], players[player.playernum]->entity) / 20.f); | |||
| 16221 | zeroVal = std::min(1.0, zeroVal); | |||
| 16222 | stats[player.playernum]->CHR = stat; | |||
| 16223 | ||||
| 16224 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("stat_selling_value_format").c_str(), (normalVal - zeroVal) * 100.0); | |||
| 16225 | } | |||
| 16226 | break; | |||
| 16227 | default: | |||
| 16228 | break; | |||
| 16229 | } | |||
| 16230 | entryValue->setColor(hudColors.characterSheetNeutral); | |||
| 16231 | if ( value < 0 ) | |||
| 16232 | { | |||
| 16233 | entryValue->setColor(hudColors.characterSheetRed); | |||
| 16234 | } | |||
| 16235 | else if ( value > 0 ) | |||
| 16236 | { | |||
| 16237 | entryValue->setColor(hudColors.characterSheetGreen); | |||
| 16238 | } | |||
| 16239 | entryValue->setText(valueBuf); | |||
| 16240 | entryValue->setSize(entry->getSize()); | |||
| 16241 | entryValue->setHJustify(Frame::justify_t::LEFT); | |||
| 16242 | entryValue->setVJustify(Field::justify_t::TOP); | |||
| 16243 | ||||
| 16244 | auto txtValueBackingFrame = characterSheetTooltipTextBackingFrames[player.playernum][4]; | |||
| 16245 | SDL_Rect backingFramePos = entryValue->getSize(); | |||
| 16246 | auto txtValueGet = Text::get(entryValue->getText(), entryValue->getFont(), | |||
| 16247 | entryValue->getTextColor(), entryValue->getOutlineColor()); | |||
| 16248 | longestValue = std::max(longestValue, txtValueGet->getWidth()); | |||
| 16249 | backingFramePos.x = backingFramePos.x + backingFramePos.w; | |||
| 16250 | backingFramePos.h = actualFont->height(true) + extraTextHeightForLowerCharacters - 2; | |||
| 16251 | valueSizes[4] = std::make_pair(entryValue, backingFramePos); | |||
| 16252 | txtValueBackingFrame->setDisabled(false); | |||
| 16253 | } | |||
| 16254 | if ( element == SHEET_PER || element == SHEET_DEX ) | |||
| 16255 | { | |||
| 16256 | // stat extra number display | |||
| 16257 | currentHeight += padyMid; | |||
| 16258 | auto entry = characterSheetTooltipTextFields[player.playernum][9]; assert(entry)(static_cast<void> (0)); | |||
| 16259 | entry->setDisabled(false); | |||
| 16260 | char buf[128] = ""; | |||
| 16261 | if ( element == SHEET_DEX ) | |||
| 16262 | { | |||
| 16263 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_dex_movement_bonus").c_str()); | |||
| 16264 | } | |||
| 16265 | else if ( element == SHEET_PER ) | |||
| 16266 | { | |||
| 16267 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("stat_per_sneaking_bonus").c_str()); | |||
| 16268 | } | |||
| 16269 | entry->setText(buf); | |||
| 16270 | entry->setVJustify(Field::justify_t::TOP); | |||
| 16271 | ||||
| 16272 | SDL_Rect entryPos = entry->getSize(); | |||
| 16273 | entryPos.x = padx + padxMid; | |||
| 16274 | entryPos.y = currentHeight; | |||
| 16275 | entryPos.w = txtPos.w - (padxMid * 2); | |||
| 16276 | entry->setSize(entryPos); | |||
| 16277 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry9 != entry->getText() ) | |||
| 16278 | { | |||
| 16279 | entry->reflowTextToFit(0); | |||
| 16280 | charsheetTooltipCache[player.playernum].textEntries[element].entry9 = entry->getText(); | |||
| 16281 | } | |||
| 16282 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 16283 | entry->setSize(entryPos); | |||
| 16284 | entry->setColor(defaultColor); | |||
| 16285 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 16286 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 16287 | ||||
| 16288 | auto entryValue = characterSheetTooltipTextFields[player.playernum][10]; assert(entry)(static_cast<void> (0)); | |||
| 16289 | entryValue->setDisabled(false); | |||
| 16290 | char valueBuf[128] = ""; | |||
| 16291 | int value = 0; | |||
| 16292 | switch ( element ) | |||
| 16293 | { | |||
| 16294 | case SHEET_STR: | |||
| 16295 | break; | |||
| 16296 | case SHEET_DEX: | |||
| 16297 | { | |||
| 16298 | Sint32 STR = statGetSTR(stats[player.playernum], players[player.playernum]->entity); | |||
| 16299 | real_t weightratio = player.movement.getWeightRatio(player.movement.getCharacterModifiedWeight(), STR); | |||
| 16300 | Sint32 DEX = statGetDEX(stats[player.playernum], players[player.playernum]->entity); | |||
| 16301 | real_t speedFactor1 = player.movement.getSpeedFactor(weightratio, 0); | |||
| 16302 | real_t speedFactor2 = player.movement.getSpeedFactor(weightratio, DEX); | |||
| 16303 | real_t maxSpeed = player.movement.getMaximumSpeed(); | |||
| 16304 | ||||
| 16305 | real_t noDEXPercent = 100.0 * speedFactor1 / std::fmax(.01, maxSpeed); | |||
| 16306 | real_t currentPercent = 100.0 * speedFactor2 / std::fmax(.01, maxSpeed); | |||
| 16307 | ||||
| 16308 | real_t displayValue = currentPercent - noDEXPercent; | |||
| 16309 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("stat_movement_value_format").c_str(), displayValue); | |||
| 16310 | } | |||
| 16311 | break; | |||
| 16312 | case SHEET_CON: | |||
| 16313 | break; | |||
| 16314 | case SHEET_INT: | |||
| 16315 | break; | |||
| 16316 | case SHEET_PER: | |||
| 16317 | { | |||
| 16318 | const int PER = statGetPER(stats[player.playernum], players[player.playernum]->entity); | |||
| 16319 | const int range_bonus = std::min(std::max(0, PER / 5), 2); | |||
| 16320 | const int sneakingBonus = range_bonus + 2; | |||
| 16321 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("stat_light_value_format").c_str(), sneakingBonus); | |||
| 16322 | } | |||
| 16323 | break; | |||
| 16324 | case SHEET_CHR: | |||
| 16325 | break; | |||
| 16326 | default: | |||
| 16327 | break; | |||
| 16328 | } | |||
| 16329 | entryValue->setColor(hudColors.characterSheetNeutral); | |||
| 16330 | if ( value < 0 ) | |||
| 16331 | { | |||
| 16332 | entryValue->setColor(hudColors.characterSheetRed); | |||
| 16333 | } | |||
| 16334 | else if ( value > 0 ) | |||
| 16335 | { | |||
| 16336 | entryValue->setColor(hudColors.characterSheetGreen); | |||
| 16337 | } | |||
| 16338 | entryValue->setText(valueBuf); | |||
| 16339 | entryValue->setSize(entry->getSize()); | |||
| 16340 | entryValue->setHJustify(Frame::justify_t::LEFT); | |||
| 16341 | entryValue->setVJustify(Field::justify_t::TOP); | |||
| 16342 | ||||
| 16343 | auto txtValueBackingFrame = characterSheetTooltipTextBackingFrames[player.playernum][5]; | |||
| 16344 | SDL_Rect backingFramePos = entryValue->getSize(); | |||
| 16345 | auto txtValueGet = Text::get(entryValue->getText(), entryValue->getFont(), | |||
| 16346 | entryValue->getTextColor(), entryValue->getOutlineColor()); | |||
| 16347 | longestValue = std::max(longestValue, txtValueGet->getWidth()); | |||
| 16348 | backingFramePos.x = backingFramePos.x + backingFramePos.w; | |||
| 16349 | backingFramePos.h = actualFont->height(true) + extraTextHeightForLowerCharacters - 2; | |||
| 16350 | valueSizes[5] = std::make_pair(entryValue, backingFramePos); | |||
| 16351 | txtValueBackingFrame->setDisabled(false); | |||
| 16352 | } | |||
| 16353 | ||||
| 16354 | for ( int index = 1; index <= NUM_CHARSHEET_TOOLTIP_BACKING_FRAMES; ++index ) | |||
| 16355 | { | |||
| 16356 | auto txtValueBackingFrame = characterSheetTooltipTextBackingFrames[player.playernum][index]; | |||
| 16357 | if ( txtValueBackingFrame->isDisabled() ) | |||
| 16358 | { | |||
| 16359 | continue; | |||
| 16360 | } | |||
| 16361 | if ( valueSizes.find(index) == valueSizes.end() ) | |||
| 16362 | { | |||
| 16363 | continue; | |||
| 16364 | } | |||
| 16365 | ||||
| 16366 | SDL_Rect valuePos = valueSizes[index].second; | |||
| 16367 | Field* entryValue = valueSizes[index].first; | |||
| 16368 | SDL_Rect entryValuePos = entryValue->getSize(); | |||
| 16369 | entryValuePos.x = entryValuePos.x + entryValuePos.w; | |||
| 16370 | entryValuePos.w = (int)longestValue; | |||
| 16371 | entryValuePos.x -= entryValuePos.w; | |||
| 16372 | entryValuePos.x -= 8; | |||
| 16373 | entryValue->setSize(entryValuePos); | |||
| 16374 | ||||
| 16375 | valuePos.w = (int)longestValue + 16; | |||
| 16376 | valuePos.x -= (valuePos.w); | |||
| 16377 | valuePos.y -= 3; | |||
| 16378 | valuePos.h += 4; | |||
| 16379 | ||||
| 16380 | txtValueBackingFrame->setSize(valuePos); | |||
| 16381 | ||||
| 16382 | imageResizeToContainer9x9(txtValueBackingFrame, SDL_Rect{ 0, 0, valuePos.w, valuePos.h }, skillsheetEffectBackgroundImages); | |||
| 16383 | } | |||
| 16384 | ||||
| 16385 | { | |||
| 16386 | currentHeight += padyMid; | |||
| 16387 | ||||
| 16388 | div->pos.x = padx; | |||
| 16389 | div->pos.y = currentHeight; | |||
| 16390 | div->pos.w = txtPos.w; | |||
| 16391 | div->disabled = false; | |||
| 16392 | ||||
| 16393 | currentHeight += padyMid; | |||
| 16394 | ||||
| 16395 | auto entry = characterSheetTooltipTextFields[player.playernum][11]; assert(entry)(static_cast<void> (0)); | |||
| 16396 | entry->setDisabled(false); | |||
| 16397 | char buf[512] = ""; | |||
| 16398 | ||||
| 16399 | std::string descTextFormatted = "\x1E "; | |||
| 16400 | for ( auto s : descText ) | |||
| 16401 | { | |||
| 16402 | descTextFormatted += s; | |||
| 16403 | if ( s == '\n' ) | |||
| 16404 | { | |||
| 16405 | descTextFormatted += "\x1E "; | |||
| 16406 | } | |||
| 16407 | } | |||
| 16408 | ||||
| 16409 | snprintf(buf, sizeof(buf), "%s", descTextFormatted.c_str()); | |||
| 16410 | entry->setText(buf); | |||
| 16411 | ||||
| 16412 | SDL_Rect entryPos = entry->getSize(); | |||
| 16413 | entryPos.x = padx; | |||
| 16414 | entryPos.y = currentHeight; | |||
| 16415 | entryPos.w = txtPos.w; | |||
| 16416 | entry->setSize(entryPos); | |||
| 16417 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry11 != entry->getText() ) | |||
| 16418 | { | |||
| 16419 | entry->reflowTextToFit(0); | |||
| 16420 | charsheetTooltipCache[player.playernum].textEntries[element].entry11 = entry->getText(); | |||
| 16421 | } | |||
| 16422 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 16423 | entry->setSize(entryPos); | |||
| 16424 | entry->setColor(hudColors.characterSheetOffWhiteText); | |||
| 16425 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 16426 | ||||
| 16427 | currentHeight += padyMid / 4; | |||
| 16428 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 16429 | } | |||
| 16430 | ||||
| 16431 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 16432 | if ( tooltipJustify == PANEL_JUSTIFY_RIGHT ) | |||
| 16433 | { | |||
| 16434 | tooltipPos.x = pos.x - tooltipPos.w; | |||
| 16435 | } | |||
| 16436 | else | |||
| 16437 | { | |||
| 16438 | tooltipPos.x = pos.x; | |||
| 16439 | } | |||
| 16440 | tooltipPos.y = pos.y; | |||
| 16441 | ||||
| 16442 | tooltipFrame->setSize(tooltipPos); | |||
| 16443 | imageResizeToContainer9x9(tooltipFrame, SDL_Rect{ 0, 0, tooltipPos.w, tooltipPos.h }, | |||
| 16444 | skillsheetEffectBackgroundImages); | |||
| 16445 | } | |||
| 16446 | else if ( element >= Player::CharacterSheet_t::SHEET_ATK && element <= Player::CharacterSheet_t::SHEET_WGT ) | |||
| 16447 | { | |||
| 16448 | AttackHoverText_t attackHoverTextInfo; | |||
| 16449 | Sint32 attackPower = displayAttackPower(player.playernum, attackHoverTextInfo); | |||
| 16450 | ||||
| 16451 | //#ifndef NDEBUG | |||
| 16452 | // if ( keystatus[SDLK_V] ) | |||
| 16453 | // { | |||
| 16454 | // keystatus[SDLK_V] = 0; | |||
| 16455 | // messagePlayer(player.playernum, MESSAGE_DEBUG, "Remove this"); | |||
| 16456 | // stats[player.playernum]->playerRace = RACE_AUTOMATON; | |||
| 16457 | // stats[player.playernum]->appearance = 0; | |||
| 16458 | // } | |||
| 16459 | // if ( keystatus[SDLK_B] ) | |||
| 16460 | // { | |||
| 16461 | // keystatus[SDLK_B] = 0; | |||
| 16462 | // messagePlayer(player.playernum, MESSAGE_DEBUG, "Remove this"); | |||
| 16463 | // stats[player.playernum]->playerRace = RACE_INSECTOID; | |||
| 16464 | // stats[player.playernum]->appearance = 0; | |||
| 16465 | // } | |||
| 16466 | //#endif // !NDEBUG | |||
| 16467 | ||||
| 16468 | bool isAutomatonHTRegen = stats[player.playernum]->type == AUTOMATON; | |||
| 16469 | bool isInsectoidENRegen = (stats[player.playernum]->playerRace == RACE_INSECTOID && stats[player.playernum]->appearance == 0); | |||
| 16470 | ||||
| 16471 | auto tooltipTopLeft = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 16472 | tooltipTopLeft->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TL_Blue_00.png"; | |||
| 16473 | auto tooltipTop = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 16474 | tooltipTop->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_T_Blue_00.png"; | |||
| 16475 | auto tooltipTopRight = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 16476 | tooltipTopRight->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TR_Blue_00.png"; | |||
| 16477 | imageSetWidthHeight9x9(tooltipFrame, skillsheetEffectBackgroundImages); | |||
| 16478 | ||||
| 16479 | int maxWidth = 260; | |||
| 16480 | if ( getHoverTextString("attributes_max_tooltip_width") != defaultString ) | |||
| 16481 | { | |||
| 16482 | maxWidth = std::max(0, std::stoi(getHoverTextString("attributes_max_tooltip_width"))); | |||
| 16483 | } | |||
| 16484 | int minWidth = 0; | |||
| 16485 | if ( getHoverTextString("attributes_min_tooltip_width") != defaultString ) | |||
| 16486 | { | |||
| 16487 | minWidth = std::max(0, std::stoi(getHoverTextString("attributes_min_tooltip_width"))); | |||
| 16488 | } | |||
| 16489 | const int padx = 16; | |||
| 16490 | const int pady1 = 8; | |||
| 16491 | const int pady2 = 4; | |||
| 16492 | const int padxMid = 4; | |||
| 16493 | const int padyMid = 8; | |||
| 16494 | SDL_Rect tooltipPos = SDL_Rect{ 400, 0, maxWidth, 100 }; | |||
| 16495 | ||||
| 16496 | std::string titleText = ""; | |||
| 16497 | std::string descText = ""; | |||
| 16498 | int value = 0; | |||
| 16499 | switch ( element ) | |||
| 16500 | { | |||
| 16501 | case SHEET_ATK: | |||
| 16502 | { | |||
| 16503 | char descBuf[256]; | |||
| 16504 | std::string skillName = "-"; | |||
| 16505 | for ( auto& skill : player.skillSheet.skillSheetData.skillEntries ) | |||
| 16506 | { | |||
| 16507 | if ( skill.skillId == attackHoverTextInfo.proficiency ) | |||
| 16508 | { | |||
| 16509 | skillName = skill.name; | |||
| 16510 | break; | |||
| 16511 | } | |||
| 16512 | } | |||
| 16513 | titleText = getHoverTextString("attributes_atk_title"); | |||
| 16514 | txtRightAlignHint->setText(""); | |||
| 16515 | txtRightAlignHint->setDisabled(false); | |||
| 16516 | if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_UNARMED ) | |||
| 16517 | { | |||
| 16518 | txtRightAlignHint->setText(getHoverTextString("attributes_atk_title_unarmed").c_str()); | |||
| 16519 | } | |||
| 16520 | else if ( stats[player.playernum]->weapon ) | |||
| 16521 | { | |||
| 16522 | Item* item = stats[player.playernum]->weapon; | |||
| 16523 | if ( item->type >= WOODEN_SHIELD && item->type < NUMITEMS ) | |||
| 16524 | { | |||
| 16525 | char itemNameBuf[128]; | |||
| 16526 | if ( itemCategory(item) == MAGICSTAFF ) | |||
| 16527 | { | |||
| 16528 | snprintf(itemNameBuf, sizeof(itemNameBuf), "%s (%+d)", item->getName(), item->beatitude); | |||
| 16529 | std::string itemNameStr = itemNameBuf; | |||
| 16530 | capitalizeString(itemNameStr); | |||
| 16531 | txtRightAlignHint->setText(itemNameStr.c_str()); | |||
| 16532 | } | |||
| 16533 | else | |||
| 16534 | { | |||
| 16535 | snprintf(itemNameBuf, sizeof(itemNameBuf), "%s %s (%+d)", | |||
| 16536 | ItemTooltips.getItemStatusAdjective(item->type, item->status).c_str(), item->getName(), item->beatitude); | |||
| 16537 | txtRightAlignHint->setText(itemNameBuf); | |||
| 16538 | } | |||
| 16539 | } | |||
| 16540 | } | |||
| 16541 | if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_MELEE_WEAPON | |||
| 16542 | || attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_WHIP ) | |||
| 16543 | { | |||
| 16544 | snprintf(descBuf, sizeof(descBuf), getHoverTextString("attributes_atk_melee_desc").c_str(), skillName.c_str()); | |||
| 16545 | descText = descBuf; | |||
| 16546 | } | |||
| 16547 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_UNARMED ) | |||
| 16548 | { | |||
| 16549 | snprintf(descBuf, sizeof(descBuf), getHoverTextString("attributes_atk_unarmed_desc").c_str(), skillName.c_str()); | |||
| 16550 | descText = descBuf; | |||
| 16551 | } | |||
| 16552 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_RANGED ) | |||
| 16553 | { | |||
| 16554 | snprintf(descBuf, sizeof(descBuf), getHoverTextString("attributes_atk_ranged_desc").c_str(), skillName.c_str()); | |||
| 16555 | descText = descBuf; | |||
| 16556 | } | |||
| 16557 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_THROWN ) | |||
| 16558 | { | |||
| 16559 | snprintf(descBuf, sizeof(descBuf), getHoverTextString("attributes_atk_thrown_desc").c_str(), skillName.c_str()); | |||
| 16560 | descText = descBuf; | |||
| 16561 | } | |||
| 16562 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_THROWN_GEM ) | |||
| 16563 | { | |||
| 16564 | snprintf(descBuf, sizeof(descBuf), getHoverTextString("attributes_atk_gem_desc").c_str(), skillName.c_str()); | |||
| 16565 | descText = descBuf; | |||
| 16566 | } | |||
| 16567 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_THROWN_POTION ) | |||
| 16568 | { | |||
| 16569 | snprintf(descBuf, sizeof(descBuf), getHoverTextString("attributes_atk_potion_desc").c_str(), skillName.c_str()); | |||
| 16570 | descText = descBuf; | |||
| 16571 | } | |||
| 16572 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_PICKAXE ) | |||
| 16573 | { | |||
| 16574 | snprintf(descBuf, sizeof(descBuf), getHoverTextString("attributes_atk_pickaxe_desc").c_str()); | |||
| 16575 | descText = descBuf; | |||
| 16576 | } | |||
| 16577 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_MAGICSTAFF ) | |||
| 16578 | { | |||
| 16579 | snprintf(descBuf, sizeof(descBuf), getHoverTextString("attributes_atk_magicstaff_desc").c_str()); | |||
| 16580 | descText = descBuf; | |||
| 16581 | } | |||
| 16582 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_TOOL ) | |||
| 16583 | { | |||
| 16584 | snprintf(descBuf, sizeof(descBuf), getHoverTextString("attributes_atk_tool_desc").c_str()); | |||
| 16585 | descText = descBuf; | |||
| 16586 | } | |||
| 16587 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_TOOL_TRAP ) | |||
| 16588 | { | |||
| 16589 | snprintf(descBuf, sizeof(descBuf), getHoverTextString("attributes_atk_tinker_tool_desc").c_str()); | |||
| 16590 | descText = descBuf; | |||
| 16591 | } | |||
| 16592 | else | |||
| 16593 | { | |||
| 16594 | descText = ""; | |||
| 16595 | } | |||
| 16596 | } | |||
| 16597 | break; | |||
| 16598 | case SHEET_AC: | |||
| 16599 | titleText = getHoverTextString("attributes_ac_title"); | |||
| 16600 | descText = getHoverTextString("attributes_ac_desc"); | |||
| 16601 | break; | |||
| 16602 | case SHEET_POW: | |||
| 16603 | titleText = getHoverTextString("attributes_pwr_title"); | |||
| 16604 | descText = getHoverTextString("attributes_pwr_desc"); | |||
| 16605 | break; | |||
| 16606 | case SHEET_RES: | |||
| 16607 | titleText = getHoverTextString("attributes_res_title"); | |||
| 16608 | descText = getHoverTextString("attributes_res_desc"); | |||
| 16609 | break; | |||
| 16610 | case SHEET_RGN: | |||
| 16611 | titleText = getHoverTextString("attributes_rgn_hp_title"); | |||
| 16612 | if ( !(svFlags & SV_FLAG_HUNGER) ) | |||
| 16613 | { | |||
| 16614 | descText = getHoverTextString("attributes_rgn_hp_desc_no_hunger"); | |||
| 16615 | } | |||
| 16616 | else | |||
| 16617 | { | |||
| 16618 | descText = getHoverTextString("attributes_rgn_hp_desc"); | |||
| 16619 | } | |||
| 16620 | break; | |||
| 16621 | case SHEET_RGN_MP: | |||
| 16622 | if ( isAutomatonHTRegen ) | |||
| 16623 | { | |||
| 16624 | titleText = getHoverTextString("attributes_rgn_ht_title"); | |||
| 16625 | descText = getHoverTextString("attributes_rgn_ht_desc"); | |||
| 16626 | } | |||
| 16627 | else if ( isInsectoidENRegen ) | |||
| 16628 | { | |||
| 16629 | titleText = getHoverTextString("attributes_rgn_en_title"); | |||
| 16630 | if ( !(svFlags & SV_FLAG_HUNGER) ) | |||
| 16631 | { | |||
| 16632 | descText = getHoverTextString("attributes_rgn_en_desc_no_hunger"); | |||
| 16633 | } | |||
| 16634 | else | |||
| 16635 | { | |||
| 16636 | descText = getHoverTextString("attributes_rgn_en_desc"); | |||
| 16637 | } | |||
| 16638 | } | |||
| 16639 | else | |||
| 16640 | { | |||
| 16641 | titleText = getHoverTextString("attributes_rgn_mp_title"); | |||
| 16642 | descText = getHoverTextString("attributes_rgn_mp_desc"); | |||
| 16643 | } | |||
| 16644 | break; | |||
| 16645 | case SHEET_WGT: | |||
| 16646 | titleText = getHoverTextString("attributes_wgt_title"); | |||
| 16647 | descText = getHoverTextString("attributes_wgt_desc"); | |||
| 16648 | break; | |||
| 16649 | default: | |||
| 16650 | break; | |||
| 16651 | } | |||
| 16652 | ||||
| 16653 | txt->setText(titleText.c_str()); | |||
| 16654 | SDL_Rect txtPos = SDL_Rect{ padx, pady1 - 2, maxWidth - padx * 2, 80 }; | |||
| 16655 | txt->setSize(txtPos); | |||
| 16656 | if ( charsheetTooltipCache[player.playernum].textEntries[element].title != txt->getText() ) | |||
| 16657 | { | |||
| 16658 | txt->reflowTextToFit(0); | |||
| 16659 | charsheetTooltipCache[player.playernum].textEntries[element].title = txt->getText(); | |||
| 16660 | } | |||
| 16661 | txt->setColor(hudColors.characterSheetHeadingText); | |||
| 16662 | Font* actualFont = Font::get(txt->getFont()); | |||
| 16663 | int txtHeight = txt->getNumTextLines() * actualFont->height(true); | |||
| 16664 | txtPos.h = txtHeight + 4; | |||
| 16665 | auto txtGet = Text::get(txt->getLongestLine().c_str(), txt->getFont(), | |||
| 16666 | txt->getTextColor(), txt->getOutlineColor()); | |||
| 16667 | txtPos.w = txtGet->getWidth(); | |||
| 16668 | txtPos.w = std::max(minWidth - padx * 2, txtPos.w); | |||
| 16669 | txt->setSize(txtPos); | |||
| 16670 | ||||
| 16671 | txtRightAlignHint->setSize(txtPos); | |||
| 16672 | txtRightAlignHint->setHJustify(Field::justify_t::RIGHT); | |||
| 16673 | ||||
| 16674 | tooltipPos.w = (txtPos.w + padx * 2); | |||
| 16675 | ||||
| 16676 | unsigned int longestValue = 0; | |||
| 16677 | std::map<int, std::pair<Field*, SDL_Rect>> valueSizes; | |||
| 16678 | ||||
| 16679 | int currentHeight = txtPos.y + (actualFont->height(true) * 1) + 2; | |||
| 16680 | const int extraTextHeightForLowerCharacters = 4; | |||
| 16681 | int currentTextFieldIndex = 1; | |||
| 16682 | int currentTextBackingFrameIndex = 1; | |||
| 16683 | ||||
| 16684 | char buf[128] = ""; | |||
| 16685 | char valueBuf[128] = ""; | |||
| 16686 | ||||
| 16687 | if ( element == SHEET_ATK && getAttackTooltipLines(player.playernum, attackHoverTextInfo, 1, buf, valueBuf) | |||
| 16688 | || element != SHEET_ATK ) | |||
| 16689 | { | |||
| 16690 | currentHeight += padyMid; | |||
| 16691 | auto entry = characterSheetTooltipTextFields[player.playernum][currentTextFieldIndex]; assert(entry)(static_cast<void> (0)); | |||
| 16692 | ++currentTextFieldIndex; | |||
| 16693 | entry->setDisabled(false); | |||
| 16694 | switch ( element ) | |||
| 16695 | { | |||
| 16696 | case SHEET_ATK: | |||
| 16697 | break; | |||
| 16698 | case SHEET_AC: | |||
| 16699 | { | |||
| 16700 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_ac_base").c_str()); | |||
| 16701 | bool oldDefending = stats[player.playernum]->defending; | |||
| 16702 | stats[player.playernum]->defending = false; | |||
| 16703 | Sint32 armor = AC(stats[player.playernum]); | |||
| 16704 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_ac_nobonus_format").c_str(), armor); | |||
| 16705 | stats[player.playernum]->defending = oldDefending; | |||
| 16706 | } | |||
| 16707 | break; | |||
| 16708 | case SHEET_POW: | |||
| 16709 | { | |||
| 16710 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_pwr_base").c_str()); | |||
| 16711 | std::string tag = "MAGIC_SPELLPOWER_TOTAL"; | |||
| 16712 | std::string formatValue = "%d"; | |||
| 16713 | std::string pwrBonus = formatSkillSheetEffects(player.playernum, PRO_MAGIC, tag, formatValue); | |||
| 16714 | Sint32 pwr = 100 + std::stoi(pwrBonus); | |||
| 16715 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_pwr_nobonus_format").c_str(), pwr); | |||
| 16716 | } | |||
| 16717 | break; | |||
| 16718 | case SHEET_RES: | |||
| 16719 | { | |||
| 16720 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_res_base").c_str()); | |||
| 16721 | real_t resistance = 100.0 * Entity::getDamageTableMultiplier(player.entity, *stats[player.playernum], DAMAGE_TABLE_MAGIC); | |||
| 16722 | resistance /= (Entity::getMagicResistance(stats[player.playernum]) + 1); | |||
| 16723 | resistance = 100.0 - resistance; | |||
| 16724 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_res_nobonus_format").c_str(), (int)resistance); | |||
| 16725 | } | |||
| 16726 | break; | |||
| 16727 | case SHEET_RGN: | |||
| 16728 | { | |||
| 16729 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_hp_base").c_str()); | |||
| 16730 | char hpbuf[32] = ""; | |||
| 16731 | getDisplayedHPRegen(players[player.playernum]->entity, *stats[player.playernum], nullptr, hpbuf); | |||
| 16732 | if ( !(svFlags & SV_FLAG_HUNGER) ) | |||
| 16733 | { | |||
| 16734 | snprintf(valueBuf, sizeof(valueBuf), "%s", hpbuf); | |||
| 16735 | } | |||
| 16736 | else | |||
| 16737 | { | |||
| 16738 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_nobonus_format").c_str(), hpbuf); | |||
| 16739 | } | |||
| 16740 | } | |||
| 16741 | break; | |||
| 16742 | case SHEET_RGN_MP: | |||
| 16743 | { | |||
| 16744 | char mpbuf[32] = ""; | |||
| 16745 | real_t regen = getDisplayedMPRegen(players[player.playernum]->entity, *stats[player.playernum], nullptr, mpbuf); | |||
| 16746 | if ( isAutomatonHTRegen ) | |||
| 16747 | { | |||
| 16748 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_ht_base").c_str()); | |||
| 16749 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_nobonus_format").c_str(), mpbuf); | |||
| 16750 | } | |||
| 16751 | else if ( isInsectoidENRegen ) | |||
| 16752 | { | |||
| 16753 | if ( !(svFlags & SV_FLAG_HUNGER) ) | |||
| 16754 | { | |||
| 16755 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_en_base").c_str()); | |||
| 16756 | snprintf(valueBuf, sizeof(valueBuf), "%s", mpbuf); | |||
| 16757 | } | |||
| 16758 | else | |||
| 16759 | { | |||
| 16760 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_en_base").c_str()); | |||
| 16761 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_en_nobonus_format").c_str(), mpbuf); | |||
| 16762 | } | |||
| 16763 | } | |||
| 16764 | else | |||
| 16765 | { | |||
| 16766 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_mp_base").c_str()); | |||
| 16767 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_nobonus_format").c_str(), mpbuf); | |||
| 16768 | } | |||
| 16769 | } | |||
| 16770 | break; | |||
| 16771 | case SHEET_WGT: | |||
| 16772 | { | |||
| 16773 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_wgt_base").c_str()); | |||
| 16774 | int weight = player.movement.getCharacterWeight(); | |||
| 16775 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_wgt_nobonus_format").c_str(), weight); | |||
| 16776 | } | |||
| 16777 | break; | |||
| 16778 | default: | |||
| 16779 | break; | |||
| 16780 | } | |||
| 16781 | entry->setText(buf); | |||
| 16782 | entry->setVJustify(Field::justify_t::TOP); | |||
| 16783 | ||||
| 16784 | auto glyphBacking = tooltipFrame->findImage("glyph 1"); | |||
| 16785 | glyphBacking->disabled = false; | |||
| 16786 | glyphBacking->path = getHoverTextString("icon_backing_path"); | |||
| 16787 | glyphBacking->pos.x = padx + padxMid + 4; | |||
| 16788 | glyphBacking->pos.y = currentHeight + 6; | |||
| 16789 | glyphBacking->pos.w = 44; | |||
| 16790 | glyphBacking->pos.h = 44; | |||
| 16791 | ||||
| 16792 | auto glyphIcon = tooltipFrame->findImage("glyph 2"); | |||
| 16793 | glyphIcon->disabled = false; | |||
| 16794 | glyphIcon->path = ""; | |||
| 16795 | switch ( element ) | |||
| 16796 | { | |||
| 16797 | case SHEET_ATK: | |||
| 16798 | if ( attackHoverTextInfo.proficiency == -1 ) | |||
| 16799 | { | |||
| 16800 | glyphIcon->path = getHoverTextString("icon_atk_path"); | |||
| 16801 | } | |||
| 16802 | else if (attackHoverTextInfo.proficiency >= 0 && attackHoverTextInfo.proficiency < NUMPROFICIENCIES ) | |||
| 16803 | { | |||
| 16804 | for ( auto& skill : player.skillSheet.skillSheetData.skillEntries ) | |||
| 16805 | { | |||
| 16806 | if ( skill.skillId == attackHoverTextInfo.proficiency ) | |||
| 16807 | { | |||
| 16808 | if ( skillCapstoneUnlocked(player.playernum, attackHoverTextInfo.proficiency) ) | |||
| 16809 | { | |||
| 16810 | glyphIcon->path = skill.skillIconPathLegend; | |||
| 16811 | } | |||
| 16812 | else | |||
| 16813 | { | |||
| 16814 | glyphIcon->path = skill.skillIconPath; | |||
| 16815 | } | |||
| 16816 | break; | |||
| 16817 | } | |||
| 16818 | } | |||
| 16819 | if ( stats[player.playernum]->getModifiedProficiency(attackHoverTextInfo.proficiency) >= SKILL_LEVEL_LEGENDARY ) | |||
| 16820 | { | |||
| 16821 | glyphBacking->path = actionPromptBackingIconPath100; | |||
| 16822 | } | |||
| 16823 | else if ( stats[player.playernum]->getModifiedProficiency(attackHoverTextInfo.proficiency) >= SKILL_LEVEL_EXPERT ) | |||
| 16824 | { | |||
| 16825 | glyphBacking->path = actionPromptBackingIconPath60; | |||
| 16826 | } | |||
| 16827 | else if ( stats[player.playernum]->getModifiedProficiency(attackHoverTextInfo.proficiency) >= SKILL_LEVEL_BASIC ) | |||
| 16828 | { | |||
| 16829 | glyphBacking->path = actionPromptBackingIconPath20; | |||
| 16830 | } | |||
| 16831 | else | |||
| 16832 | { | |||
| 16833 | glyphBacking->path = actionPromptBackingIconPath00; | |||
| 16834 | } | |||
| 16835 | } | |||
| 16836 | break; | |||
| 16837 | case SHEET_AC: | |||
| 16838 | glyphIcon->path = getHoverTextString("icon_ac_path"); | |||
| 16839 | for ( auto& skill : player.skillSheet.skillSheetData.skillEntries ) | |||
| 16840 | { | |||
| 16841 | if ( skill.skillId == PRO_SHIELD ) | |||
| 16842 | { | |||
| 16843 | if ( skillCapstoneUnlocked(player.playernum, PRO_SHIELD) ) | |||
| 16844 | { | |||
| 16845 | glyphIcon->path = skill.skillIconPathLegend; | |||
| 16846 | } | |||
| 16847 | else | |||
| 16848 | { | |||
| 16849 | glyphIcon->path = skill.skillIconPath; | |||
| 16850 | } | |||
| 16851 | break; | |||
| 16852 | } | |||
| 16853 | } | |||
| 16854 | if ( stats[player.playernum]->getModifiedProficiency(PRO_SHIELD) >= SKILL_LEVEL_LEGENDARY ) | |||
| 16855 | { | |||
| 16856 | glyphBacking->path = actionPromptBackingIconPath100; | |||
| 16857 | } | |||
| 16858 | else if ( stats[player.playernum]->getModifiedProficiency(PRO_SHIELD) >= SKILL_LEVEL_EXPERT ) | |||
| 16859 | { | |||
| 16860 | glyphBacking->path = actionPromptBackingIconPath60; | |||
| 16861 | } | |||
| 16862 | else if ( stats[player.playernum]->getModifiedProficiency(PRO_SHIELD) >= SKILL_LEVEL_BASIC ) | |||
| 16863 | { | |||
| 16864 | glyphBacking->path = actionPromptBackingIconPath20; | |||
| 16865 | } | |||
| 16866 | else | |||
| 16867 | { | |||
| 16868 | glyphBacking->path = actionPromptBackingIconPath00; | |||
| 16869 | } | |||
| 16870 | break; | |||
| 16871 | case SHEET_POW: | |||
| 16872 | glyphIcon->path = getHoverTextString("icon_pwr_path"); | |||
| 16873 | break; | |||
| 16874 | case SHEET_RES: | |||
| 16875 | glyphIcon->path = getHoverTextString("icon_res_path"); | |||
| 16876 | break; | |||
| 16877 | case SHEET_RGN: | |||
| 16878 | glyphIcon->path = getHoverTextString("icon_rgn_hp_path"); | |||
| 16879 | break; | |||
| 16880 | case SHEET_RGN_MP: | |||
| 16881 | if ( isAutomatonHTRegen ) | |||
| 16882 | { | |||
| 16883 | if ( stats[player.playernum]->HUNGER <= 300 ) | |||
| 16884 | { | |||
| 16885 | glyphIcon->path = getHoverTextString("icon_rgn_ht_empty_path"); | |||
| 16886 | } | |||
| 16887 | else if ( stats[player.playernum]->HUNGER > 1200 ) | |||
| 16888 | { | |||
| 16889 | glyphIcon->path = getHoverTextString("icon_rgn_ht_superheated_path"); | |||
| 16890 | } | |||
| 16891 | else | |||
| 16892 | { | |||
| 16893 | glyphIcon->path = getHoverTextString("icon_rgn_ht_normal_path"); | |||
| 16894 | } | |||
| 16895 | } | |||
| 16896 | else | |||
| 16897 | { | |||
| 16898 | glyphIcon->path = getHoverTextString("icon_rgn_mp_path"); | |||
| 16899 | } | |||
| 16900 | break; | |||
| 16901 | case SHEET_WGT: | |||
| 16902 | glyphIcon->path = getHoverTextString("icon_wgt_path"); | |||
| 16903 | break; | |||
| 16904 | default: | |||
| 16905 | break; | |||
| 16906 | } | |||
| 16907 | glyphIcon->pos.w = 24; | |||
| 16908 | glyphIcon->pos.h = 24; | |||
| 16909 | glyphIcon->pos.x = glyphBacking->pos.x + glyphBacking->pos.w / 2 - glyphIcon->pos.w / 2; | |||
| 16910 | glyphIcon->pos.y = glyphBacking->pos.y + glyphBacking->pos.h / 2 - glyphIcon->pos.h / 2; | |||
| 16911 | ||||
| 16912 | SDL_Rect entryPos = entry->getSize(); | |||
| 16913 | entryPos.x = padx / 2 + glyphBacking->pos.x + glyphBacking->pos.w; | |||
| 16914 | entryPos.y = currentHeight; | |||
| 16915 | if ( element == SHEET_ATK ) | |||
| 16916 | { | |||
| 16917 | if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_THROWN | |||
| 16918 | || attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_THROWN_GEM | |||
| 16919 | || attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_PICKAXE ) | |||
| 16920 | { | |||
| 16921 | // fewer lines, add offset to centre the lines with the glyph | |||
| 16922 | entryPos.y += 8; | |||
| 16923 | } | |||
| 16924 | else if ( attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_DEFAULT | |||
| 16925 | || attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_TOOL | |||
| 16926 | || attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_TOOL_TRAP | |||
| 16927 | || attackHoverTextInfo.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_MAGICSTAFF ) | |||
| 16928 | { | |||
| 16929 | entryPos.y += 16; | |||
| 16930 | } | |||
| 16931 | } | |||
| 16932 | else if ( element == SHEET_RGN_MP && isInsectoidENRegen ) | |||
| 16933 | { | |||
| 16934 | entryPos.y += 16; | |||
| 16935 | } | |||
| 16936 | entryPos.w = txtPos.w - (padxMid + glyphBacking->pos.x + glyphBacking->pos.w); | |||
| 16937 | entry->setSize(entryPos); | |||
| 16938 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry1 != entry->getText() ) | |||
| 16939 | { | |||
| 16940 | entry->reflowTextToFit(0); | |||
| 16941 | charsheetTooltipCache[player.playernum].textEntries[element].entry1 = entry->getText(); | |||
| 16942 | } | |||
| 16943 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 16944 | entry->setSize(entryPos); | |||
| 16945 | entry->setColor(defaultColor); | |||
| 16946 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 16947 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 16948 | ||||
| 16949 | auto entryValue = characterSheetTooltipTextFields[player.playernum][currentTextFieldIndex]; assert(entry)(static_cast<void> (0)); | |||
| 16950 | ++currentTextFieldIndex; | |||
| 16951 | entryValue->setDisabled(false); | |||
| 16952 | int value = 0; | |||
| 16953 | switch ( element ) | |||
| 16954 | { | |||
| 16955 | case SHEET_ATK: | |||
| 16956 | break; | |||
| 16957 | case SHEET_AC: | |||
| 16958 | break; | |||
| 16959 | case SHEET_POW: | |||
| 16960 | break; | |||
| 16961 | case SHEET_RES: | |||
| 16962 | break; | |||
| 16963 | case SHEET_RGN: | |||
| 16964 | break; | |||
| 16965 | case SHEET_WGT: | |||
| 16966 | break; | |||
| 16967 | default: | |||
| 16968 | break; | |||
| 16969 | } | |||
| 16970 | entryValue->setColor(hudColors.characterSheetNeutral); | |||
| 16971 | if ( value < 0 ) | |||
| 16972 | { | |||
| 16973 | entryValue->setColor(hudColors.characterSheetRed); | |||
| 16974 | } | |||
| 16975 | entryValue->setText(valueBuf); | |||
| 16976 | SDL_Rect entryValuePos = entry->getSize(); | |||
| 16977 | entryValue->setSize(entryValuePos); | |||
| 16978 | entryValue->setHJustify(Frame::justify_t::RIGHT); | |||
| 16979 | entryValue->setVJustify(Field::justify_t::TOP); | |||
| 16980 | ||||
| 16981 | /*auto txtValueBackingFrame = tooltipFrame->findFrame("txt value backing frame 1"); | |||
| 16982 | SDL_Rect backingFramePos = entryValue->getSize(); | |||
| 16983 | auto txtValueGet = Text::get(entryValue->getText(), entryValue->getFont(), | |||
| 16984 | entryValue->getTextColor(), entryValue->getOutlineColor()); | |||
| 16985 | longestValue = std::max(longestValue, txtValueGet->getWidth()); | |||
| 16986 | backingFramePos.x = backingFramePos.x + backingFramePos.w; | |||
| 16987 | backingFramePos.h = actualFont->height(true) + extraTextHeightForLowerCharacters - 2; | |||
| 16988 | valueSizes[1] = std::make_pair(entryValue, backingFramePos); | |||
| 16989 | txtValueBackingFrame->setDisabled(false);*/ | |||
| 16990 | ++currentTextBackingFrameIndex; | |||
| 16991 | } | |||
| 16992 | ||||
| 16993 | if ( element == SHEET_ATK && getAttackTooltipLines(player.playernum, attackHoverTextInfo, 2, buf, valueBuf) | |||
| 16994 | || element != SHEET_ATK ) | |||
| 16995 | { | |||
| 16996 | currentHeight += 0; | |||
| 16997 | auto entry = characterSheetTooltipTextFields[player.playernum][currentTextFieldIndex]; assert(entry)(static_cast<void> (0)); | |||
| 16998 | ++currentTextFieldIndex; | |||
| 16999 | entry->setDisabled(false); | |||
| 17000 | switch ( element ) | |||
| 17001 | { | |||
| 17002 | case SHEET_ATK: | |||
| 17003 | break; | |||
| 17004 | case SHEET_AC: | |||
| 17005 | { | |||
| 17006 | std::string skillName = ""; | |||
| 17007 | int skillLVL = 0; | |||
| 17008 | for ( auto& skill : player.skillSheet.skillSheetData.skillEntries ) | |||
| 17009 | { | |||
| 17010 | if ( skill.skillId == PRO_SHIELD ) | |||
| 17011 | { | |||
| 17012 | skillName = skill.name; | |||
| 17013 | skillLVL = stats[player.playernum]->getModifiedProficiency(skill.skillId); | |||
| 17014 | break; | |||
| 17015 | } | |||
| 17016 | } | |||
| 17017 | snprintf(buf, sizeof(buf), getHoverTextString("attributes_ac_defending").c_str(), skillName.c_str(), skillLVL); | |||
| 17018 | std::string tag = "BLOCK_AC_INCREASE"; | |||
| 17019 | std::string blockBonus = formatSkillSheetEffects(player.playernum, PRO_SHIELD, tag, getHoverTextString("attributes_ac_bonus_format")); | |||
| 17020 | snprintf(valueBuf, sizeof(valueBuf), "%s", blockBonus.c_str()); | |||
| 17021 | } | |||
| 17022 | break; | |||
| 17023 | case SHEET_POW: | |||
| 17024 | { | |||
| 17025 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_pwr_spellbook").c_str()); | |||
| 17026 | std::string tag = "MAGIC_SPELLPOWER_INT"; | |||
| 17027 | std::string formatValue = "%d"; | |||
| 17028 | std::string pwrBonus = formatSkillSheetEffects(player.playernum, PRO_MAGIC, tag, formatValue); | |||
| 17029 | Sint32 pwr = std::stoi(pwrBonus) / 2; | |||
| 17030 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_pwr_bonus_format").c_str(), pwr); | |||
| 17031 | } | |||
| 17032 | break; | |||
| 17033 | case SHEET_RES: | |||
| 17034 | { | |||
| 17035 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_res_sources").c_str()); | |||
| 17036 | int sources = Entity::getMagicResistance(stats[player.playernum]); | |||
| 17037 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_res_sources_format").c_str(), sources); | |||
| 17038 | } | |||
| 17039 | break; | |||
| 17040 | case SHEET_RGN: | |||
| 17041 | { | |||
| 17042 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_sources").c_str()); | |||
| 17043 | int sources = Entity::getHealringFromEquipment(players[player.playernum]->entity, *stats[player.playernum], true); | |||
| 17044 | sources += Entity::getHealringFromEffects(players[player.playernum]->entity, *stats[player.playernum]); | |||
| 17045 | sources = std::min(sources, 3); | |||
| 17046 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_hp_sources_format").c_str(), sources); | |||
| 17047 | } | |||
| 17048 | break; | |||
| 17049 | case SHEET_RGN_MP: | |||
| 17050 | { | |||
| 17051 | if ( isInsectoidENRegen ) | |||
| 17052 | { | |||
| 17053 | //snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_en_sources").c_str()); | |||
| 17054 | snprintf(buf, sizeof(buf), ""); | |||
| 17055 | snprintf(valueBuf, sizeof(valueBuf), ""); | |||
| 17056 | } | |||
| 17057 | else | |||
| 17058 | { | |||
| 17059 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_sources").c_str()); | |||
| 17060 | int sources = Entity::getManaringFromEquipment(players[player.playernum]->entity, *stats[player.playernum], true); | |||
| 17061 | sources += Entity::getManaringFromEffects(players[player.playernum]->entity, *stats[player.playernum]); | |||
| 17062 | sources = std::min(sources, 3); | |||
| 17063 | if ( isAutomatonHTRegen ) | |||
| 17064 | { | |||
| 17065 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_ht_sources_format").c_str(), sources); | |||
| 17066 | } | |||
| 17067 | else | |||
| 17068 | { | |||
| 17069 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_mp_sources_format").c_str(), sources); | |||
| 17070 | } | |||
| 17071 | } | |||
| 17072 | } | |||
| 17073 | break; | |||
| 17074 | case SHEET_WGT: | |||
| 17075 | { | |||
| 17076 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_wgt_movement_speed").c_str()); | |||
| 17077 | int weight = player.movement.getCharacterModifiedWeight(); | |||
| 17078 | Sint32 STR = statGetSTR(stats[player.playernum], player.entity); | |||
| 17079 | Sint32 DEX = statGetDEX(stats[player.playernum], player.entity); | |||
| 17080 | real_t currentSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(weight, STR), DEX); | |||
| 17081 | real_t maxSpeed = player.movement.getMaximumSpeed(); | |||
| 17082 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_wgt_speed_format").c_str(), | |||
| 17083 | 100.0 * currentSpeed / std::fmax(.01, maxSpeed)); | |||
| 17084 | } | |||
| 17085 | break; | |||
| 17086 | default: | |||
| 17087 | break; | |||
| 17088 | } | |||
| 17089 | entry->setText(buf); | |||
| 17090 | entry->setVJustify(Field::justify_t::TOP); | |||
| 17091 | ||||
| 17092 | auto glyphBacking = tooltipFrame->findImage("glyph 1"); | |||
| 17093 | ||||
| 17094 | SDL_Rect entryPos = entry->getSize(); | |||
| 17095 | entryPos.x = padx / 2 + glyphBacking->pos.x + glyphBacking->pos.w; | |||
| 17096 | entryPos.y = currentHeight; | |||
| 17097 | entryPos.w = txtPos.w - (padxMid + glyphBacking->pos.x + glyphBacking->pos.w); | |||
| 17098 | entry->setSize(entryPos); | |||
| 17099 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry2 != entry->getText() ) | |||
| 17100 | { | |||
| 17101 | entry->reflowTextToFit(0); | |||
| 17102 | charsheetTooltipCache[player.playernum].textEntries[element].entry2 = entry->getText(); | |||
| 17103 | } | |||
| 17104 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 17105 | entry->setSize(entryPos); | |||
| 17106 | entry->setColor(defaultColor); | |||
| 17107 | ||||
| 17108 | if ( strcmp(buf, "") ) | |||
| 17109 | { | |||
| 17110 | // don't modify height if this is an empty line | |||
| 17111 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 17112 | } | |||
| 17113 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 17114 | ||||
| 17115 | auto entryValue = characterSheetTooltipTextFields[player.playernum][currentTextFieldIndex]; assert(entry)(static_cast<void> (0)); | |||
| 17116 | ++currentTextFieldIndex; | |||
| 17117 | entryValue->setDisabled(false); | |||
| 17118 | int value = 0; | |||
| 17119 | switch ( element ) | |||
| 17120 | { | |||
| 17121 | case SHEET_ATK: | |||
| 17122 | break; | |||
| 17123 | case SHEET_AC: | |||
| 17124 | break; | |||
| 17125 | case SHEET_POW: | |||
| 17126 | break; | |||
| 17127 | case SHEET_RES: | |||
| 17128 | break; | |||
| 17129 | case SHEET_RGN: | |||
| 17130 | break; | |||
| 17131 | case SHEET_WGT: | |||
| 17132 | break; | |||
| 17133 | default: | |||
| 17134 | break; | |||
| 17135 | } | |||
| 17136 | entryValue->setColor(hudColors.characterSheetNeutral); | |||
| 17137 | if ( value < 0 ) | |||
| 17138 | { | |||
| 17139 | entryValue->setColor(hudColors.characterSheetRed); | |||
| 17140 | } | |||
| 17141 | else if ( value > 0 ) | |||
| 17142 | { | |||
| 17143 | entryValue->setColor(hudColors.characterSheetGreen); | |||
| 17144 | } | |||
| 17145 | entryValue->setText(valueBuf); | |||
| 17146 | SDL_Rect entryValuePos = entry->getSize(); | |||
| 17147 | entryValue->setSize(entryValuePos); | |||
| 17148 | entryValue->setHJustify(Frame::justify_t::RIGHT); | |||
| 17149 | entryValue->setVJustify(Field::justify_t::TOP); | |||
| 17150 | ||||
| 17151 | /*auto txtValueBackingFrame = tooltipFrame->findFrame("txt value backing frame 2"); | |||
| 17152 | SDL_Rect backingFramePos = entryValue->getSize(); | |||
| 17153 | auto txtValueGet = Text::get(entryValue->getText(), entryValue->getFont(), | |||
| 17154 | entryValue->getTextColor(), entryValue->getOutlineColor()); | |||
| 17155 | longestValue = std::max(longestValue, txtValueGet->getWidth()); | |||
| 17156 | backingFramePos.x = backingFramePos.x + backingFramePos.w; | |||
| 17157 | backingFramePos.h = actualFont->height(true) + extraTextHeightForLowerCharacters - 2; | |||
| 17158 | valueSizes[2] = std::make_pair(entryValue, backingFramePos); | |||
| 17159 | txtValueBackingFrame->setDisabled(false);*/ | |||
| 17160 | ++currentTextBackingFrameIndex; | |||
| 17161 | } | |||
| 17162 | bool hasEntryInfoLines = false; | |||
| 17163 | if ( element == SHEET_ATK && getAttackTooltipLines(player.playernum, attackHoverTextInfo, 3, buf, valueBuf) | |||
| 17164 | || (element != SHEET_ATK | |||
| 17165 | && !(element == SHEET_RGN && !(svFlags & SV_FLAG_HUNGER)) | |||
| 17166 | && !(element == SHEET_RGN_MP && isInsectoidENRegen && !(svFlags & SV_FLAG_HUNGER)) | |||
| 17167 | )) | |||
| 17168 | { | |||
| 17169 | // extra number display - line 3 | |||
| 17170 | hasEntryInfoLines = true; | |||
| 17171 | if ( element == SHEET_ATK || element == SHEET_AC || element == SHEET_POW || element == SHEET_RES || element == SHEET_RGN | |||
| 17172 | || element == SHEET_RGN_MP || element == SHEET_WGT ) | |||
| 17173 | { | |||
| 17174 | if ( element == SHEET_RGN_MP && isInsectoidENRegen ) | |||
| 17175 | { | |||
| 17176 | currentHeight += 8; | |||
| 17177 | } | |||
| 17178 | ||||
| 17179 | // add a divider | |||
| 17180 | div2->pos.x = padx; | |||
| 17181 | div2->pos.y = currentHeight + 2 + actualFont->height(true); | |||
| 17182 | div2->pos.w = txtPos.w; | |||
| 17183 | div2->disabled = false; | |||
| 17184 | ||||
| 17185 | auto entryTotalHeading = characterSheetTooltipTextFields[player.playernum][16]; assert(entryTotalHeading)(static_cast<void> (0)); | |||
| 17186 | entryTotalHeading->setDisabled(false); | |||
| 17187 | if ( element == SHEET_ATK ) | |||
| 17188 | { | |||
| 17189 | entryTotalHeading->setText(getHoverTextString("attributes_atk_total_sum_header").c_str()); | |||
| 17190 | } | |||
| 17191 | else if ( element == SHEET_AC ) | |||
| 17192 | { | |||
| 17193 | entryTotalHeading->setText(getHoverTextString("attributes_ac_base_sum_header").c_str()); | |||
| 17194 | } | |||
| 17195 | else if ( element == SHEET_POW ) | |||
| 17196 | { | |||
| 17197 | entryTotalHeading->setText(getHoverTextString("attributes_pwr_base_sum_header").c_str()); | |||
| 17198 | } | |||
| 17199 | else if ( element == SHEET_RES ) | |||
| 17200 | { | |||
| 17201 | entryTotalHeading->setText(getHoverTextString("attributes_res_base_sum_header").c_str()); | |||
| 17202 | } | |||
| 17203 | else if ( element == SHEET_RGN ) | |||
| 17204 | { | |||
| 17205 | entryTotalHeading->setText(getHoverTextString("attributes_rgn_hp_base_sum_header").c_str()); | |||
| 17206 | } | |||
| 17207 | else if ( element == SHEET_RGN_MP ) | |||
| 17208 | { | |||
| 17209 | if ( isAutomatonHTRegen ) | |||
| 17210 | { | |||
| 17211 | entryTotalHeading->setText(getHoverTextString("attributes_rgn_ht_base_sum_header").c_str()); | |||
| 17212 | } | |||
| 17213 | else if ( isInsectoidENRegen ) | |||
| 17214 | { | |||
| 17215 | entryTotalHeading->setText(getHoverTextString("attributes_rgn_en_base_sum_header").c_str()); | |||
| 17216 | } | |||
| 17217 | else | |||
| 17218 | { | |||
| 17219 | entryTotalHeading->setText(getHoverTextString("attributes_rgn_mp_base_sum_header").c_str()); | |||
| 17220 | } | |||
| 17221 | } | |||
| 17222 | else if ( element == SHEET_WGT ) | |||
| 17223 | { | |||
| 17224 | entryTotalHeading->setText(getHoverTextString("attributes_wgt_base_sum_header").c_str()); | |||
| 17225 | } | |||
| 17226 | entryTotalHeading->setColor(hudColors.characterSheetOffWhiteText); | |||
| 17227 | entryTotalHeading->setHJustify(Field::justify_t::RIGHT); | |||
| 17228 | SDL_Rect entryPos = entryTotalHeading->getSize(); | |||
| 17229 | entryPos.x = padx + padxMid; | |||
| 17230 | entryPos.y = currentHeight + 1 - (extraTextHeightForLowerCharacters / 2); | |||
| 17231 | entryPos.w = txtPos.w - (padxMid * 2); | |||
| 17232 | entryPos.h = actualFont->height(true) + extraTextHeightForLowerCharacters; | |||
| 17233 | entryTotalHeading->setSize(entryPos); | |||
| 17234 | ||||
| 17235 | currentHeight += actualFont->height(true) + 2; // extra gap here for 'total' text. | |||
| 17236 | } | |||
| 17237 | currentHeight += padyMid; | |||
| 17238 | auto entry = characterSheetTooltipTextFields[player.playernum][currentTextFieldIndex]; assert(entry)(static_cast<void> (0)); | |||
| 17239 | ++currentTextFieldIndex; | |||
| 17240 | entry->setDisabled(false); | |||
| 17241 | int value = 0; | |||
| 17242 | switch ( element ) | |||
| 17243 | { | |||
| 17244 | case SHEET_ATK: | |||
| 17245 | break; | |||
| 17246 | case SHEET_AC: | |||
| 17247 | { | |||
| 17248 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_ac_entry_attr_bonus").c_str()); | |||
| 17249 | Sint32 CON = statGetCON(stats[player.playernum], players[player.playernum]->entity); | |||
| 17250 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_ac_bonus_format").c_str(), CON); | |||
| 17251 | } | |||
| 17252 | break; | |||
| 17253 | case SHEET_POW: | |||
| 17254 | { | |||
| 17255 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_pwr_base_value").c_str()); | |||
| 17256 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_pwr_bonus_format").c_str(), 100); | |||
| 17257 | } | |||
| 17258 | break; | |||
| 17259 | case SHEET_RES: | |||
| 17260 | { | |||
| 17261 | Monster type = stats[player.playernum]->type; | |||
| 17262 | std::string appearance = ""; | |||
| 17263 | bool aestheticOnly = false; | |||
| 17264 | if ( player.entity ) | |||
| 17265 | { | |||
| 17266 | if ( player.entity->effectPolymorph == NOTHING && stats[player.playernum]->playerRace > RACE_HUMAN ) | |||
| 17267 | { | |||
| 17268 | if ( stats[player.playernum]->appearance != 0 ) | |||
| 17269 | { | |||
| 17270 | aestheticOnly = true; | |||
| 17271 | appearance = Language::get(4068); | |||
| 17272 | type = player.entity->getMonsterFromPlayerRace(stats[player.playernum]->playerRace); | |||
| 17273 | } | |||
| 17274 | } | |||
| 17275 | } | |||
| 17276 | std::string race = getMonsterLocalizedName(type).c_str(); | |||
| 17277 | capitalizeString(race); | |||
| 17278 | ||||
| 17279 | snprintf(buf, sizeof(buf), getHoverTextString("attributes_res_base_value").c_str(), race.c_str()); | |||
| 17280 | Sint32 baseResist = damagetables[stats[player.playernum]->type][DAMAGE_TABLE_MAGIC] * 100; | |||
| 17281 | baseResist = 100 - baseResist; | |||
| 17282 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_res_bonus_format").c_str(), baseResist); | |||
| 17283 | } | |||
| 17284 | break; | |||
| 17285 | case SHEET_RGN: | |||
| 17286 | { | |||
| 17287 | Monster type = stats[player.playernum]->type; | |||
| 17288 | bool aestheticOnly = false; | |||
| 17289 | if ( player.entity ) | |||
| 17290 | { | |||
| 17291 | if ( player.entity->effectPolymorph == NOTHING && stats[player.playernum]->playerRace > RACE_HUMAN ) | |||
| 17292 | { | |||
| 17293 | if ( stats[player.playernum]->appearance != 0 ) | |||
| 17294 | { | |||
| 17295 | aestheticOnly = true; | |||
| 17296 | type = player.entity->getMonsterFromPlayerRace(stats[player.playernum]->playerRace); | |||
| 17297 | } | |||
| 17298 | } | |||
| 17299 | } | |||
| 17300 | std::string race = getMonsterLocalizedName(type).c_str(); | |||
| 17301 | capitalizeString(race); | |||
| 17302 | ||||
| 17303 | snprintf(buf, sizeof(buf), getHoverTextString("attributes_rgn_base_value").c_str(), race.c_str()); | |||
| 17304 | real_t regen = 100.0; | |||
| 17305 | if ( type == SKELETON ) | |||
| 17306 | { | |||
| 17307 | regen = 25.0; | |||
| 17308 | } | |||
| 17309 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_bonus_format").c_str(), regen); | |||
| 17310 | } | |||
| 17311 | break; | |||
| 17312 | case SHEET_RGN_MP: | |||
| 17313 | { | |||
| 17314 | if ( isAutomatonHTRegen ) | |||
| 17315 | { | |||
| 17316 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_ht_base_bonus").c_str()); | |||
| 17317 | real_t baseHTModifier = 100.f; | |||
| 17318 | if ( stats[player.playernum]->HUNGER <= 300 ) | |||
| 17319 | { | |||
| 17320 | int baseTime = getBaseManaRegen(player.entity, *stats[player.playernum]); | |||
| 17321 | real_t scaledInterval = ((60 * baseTime) / (std::max(stats[player.playernum]->MAXMP, 1))); | |||
| 17322 | baseHTModifier = scaledInterval / TICKS_PER_SECOND50; | |||
| 17323 | baseHTModifier /= -6.0; // degrade faster | |||
| 17324 | real_t nominalRegen = MAGIC_REGEN_TIME300 / TICKS_PER_SECOND50; | |||
| 17325 | baseHTModifier = (nominalRegen / baseHTModifier) * 100.0; | |||
| 17326 | } | |||
| 17327 | else if ( stats[player.playernum]->HUNGER > 1200 ) | |||
| 17328 | { | |||
| 17329 | if ( stats[player.playernum]->MP / static_cast<real_t>(std::max(1, stats[player.playernum]->MAXMP)) <= 0.5 ) | |||
| 17330 | { | |||
| 17331 | baseHTModifier *= 4; // increase faster at < 50% mana | |||
| 17332 | } | |||
| 17333 | else | |||
| 17334 | { | |||
| 17335 | baseHTModifier *= 2; // increase less faster at > 50% mana | |||
| 17336 | } | |||
| 17337 | } | |||
| 17338 | else | |||
| 17339 | { | |||
| 17340 | // normal manaRegenInterval 300-1200 hunger. | |||
| 17341 | } | |||
| 17342 | //baseHTModifier /= 100.0; | |||
| 17343 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_ht_bonus_format").c_str(), baseHTModifier); | |||
| 17344 | } | |||
| 17345 | else if ( isInsectoidENRegen ) | |||
| 17346 | { | |||
| 17347 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_en_base_bonus").c_str()); | |||
| 17348 | ||||
| 17349 | real_t normalRegenTime = (1000.f * 30 * 1.5) / static_cast<float>(TICKS_PER_SECOND50); // 30 base, insectoid does 1.5x in getHungerTickRate() | |||
| 17350 | //normalRegenTime = (1000.f * (Entity::getHungerTickRate(stats[player.playernum], true, true)) / static_cast<float>(TICKS_PER_SECOND)); | |||
| 17351 | normalRegenTime /= (std::max(stats[player.playernum]->MAXMP, 1)); // time for 1 mana in seconds | |||
| 17352 | normalRegenTime *= TICKS_PER_SECOND50; // game ticks for 1 mana | |||
| 17353 | ||||
| 17354 | real_t modifiedRegenTime = (1000.f * (Entity::getHungerTickRate(stats[player.playernum], true, false)) / static_cast<float>(TICKS_PER_SECOND50)); | |||
| 17355 | modifiedRegenTime /= (std::max(stats[player.playernum]->MAXMP, 1)); // time for 1 mana in seconds | |||
| 17356 | modifiedRegenTime *= TICKS_PER_SECOND50; // game ticks for 1 mana | |||
| 17357 | ||||
| 17358 | real_t displayValue = 100.0 * (normalRegenTime / modifiedRegenTime); | |||
| 17359 | ||||
| 17360 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_en_bonus_format").c_str(), displayValue); | |||
| 17361 | } | |||
| 17362 | else | |||
| 17363 | { | |||
| 17364 | Monster type = stats[player.playernum]->type; | |||
| 17365 | bool aestheticOnly = false; | |||
| 17366 | if ( player.entity ) | |||
| 17367 | { | |||
| 17368 | if ( player.entity->effectPolymorph == NOTHING && stats[player.playernum]->playerRace > RACE_HUMAN ) | |||
| 17369 | { | |||
| 17370 | if ( stats[player.playernum]->appearance != 0 ) | |||
| 17371 | { | |||
| 17372 | aestheticOnly = true; | |||
| 17373 | type = player.entity->getMonsterFromPlayerRace(stats[player.playernum]->playerRace); | |||
| 17374 | } | |||
| 17375 | } | |||
| 17376 | } | |||
| 17377 | std::string race = getMonsterLocalizedName(type).c_str(); | |||
| 17378 | capitalizeString(race); | |||
| 17379 | ||||
| 17380 | snprintf(buf, sizeof(buf), getHoverTextString("attributes_rgn_base_value").c_str(), race.c_str()); | |||
| 17381 | real_t regen = 100.0; | |||
| 17382 | if ( type == SKELETON ) | |||
| 17383 | { | |||
| 17384 | regen = 25.0; | |||
| 17385 | } | |||
| 17386 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_bonus_format").c_str(), regen); | |||
| 17387 | } | |||
| 17388 | } | |||
| 17389 | break; | |||
| 17390 | case SHEET_WGT: | |||
| 17391 | { | |||
| 17392 | int weight = player.movement.getCharacterModifiedWeight(); | |||
| 17393 | //int equippedWeightTotal = player.movement.getCharacterEquippedWeight(); | |||
| 17394 | //int equippedWeight = player.movement.getCharacterModifiedWeight(&equippedWeightTotal); | |||
| 17395 | //int goldWeightTotal = stats[player.playernum]->GOLD / 100; | |||
| 17396 | //int goldWeight = player.movement.getCharacterModifiedWeight(&goldWeightTotal); | |||
| 17397 | Sint32 STR = statGetSTR(stats[player.playernum], player.entity); | |||
| 17398 | Sint32 DEX = statGetDEX(stats[player.playernum], player.entity); | |||
| 17399 | //real_t currentEquippedSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(equippedWeight, STR), DEX); | |||
| 17400 | real_t currentSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(weight, STR), DEX); | |||
| 17401 | real_t noWeightSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(0, STR), DEX); | |||
| 17402 | //real_t goldSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(goldWeight, STR), DEX); | |||
| 17403 | real_t maxSpeed = player.movement.getMaximumSpeed(); | |||
| 17404 | ||||
| 17405 | real_t currentSpeedPercent = 100.0 * currentSpeed / std::fmax(.01, maxSpeed); | |||
| 17406 | //real_t currentEquippedSpeedPercent = 100.0 * currentEquippedSpeed / std::fmax(.01, maxSpeed); | |||
| 17407 | real_t noWeightSpeedPercent = 100.0 * noWeightSpeed / std::fmax(.01, maxSpeed); | |||
| 17408 | //real_t goldSpeedPercent = 100.0 * goldSpeed / std::fmax(.01, maxSpeed); | |||
| 17409 | ||||
| 17410 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_wgt_attributes_bonus").c_str()); | |||
| 17411 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_wgt_speed_bonus_format").c_str(), | |||
| 17412 | currentSpeedPercent + (noWeightSpeedPercent - currentSpeedPercent) /*+ (goldSpeedPercent - noWeightSpeedPercent)*/); | |||
| 17413 | } | |||
| 17414 | break; | |||
| 17415 | default: | |||
| 17416 | break; | |||
| 17417 | } | |||
| 17418 | entry->setText(buf); | |||
| 17419 | entry->setVJustify(Field::justify_t::TOP); | |||
| 17420 | ||||
| 17421 | SDL_Rect entryPos = entry->getSize(); | |||
| 17422 | entryPos.x = padx + padxMid; | |||
| 17423 | entryPos.y = currentHeight; | |||
| 17424 | entryPos.w = txtPos.w - (padxMid * 2); | |||
| 17425 | entry->setSize(entryPos); | |||
| 17426 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry3 != entry->getText() ) | |||
| 17427 | { | |||
| 17428 | entry->reflowTextToFit(0); | |||
| 17429 | charsheetTooltipCache[player.playernum].textEntries[element].entry3 = entry->getText(); | |||
| 17430 | } | |||
| 17431 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 17432 | entry->setSize(entryPos); | |||
| 17433 | entry->setColor(defaultColor); | |||
| 17434 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 17435 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 17436 | ||||
| 17437 | auto entryValue = characterSheetTooltipTextFields[player.playernum][currentTextFieldIndex]; assert(entry)(static_cast<void> (0)); | |||
| 17438 | ++currentTextFieldIndex; | |||
| 17439 | entryValue->setDisabled(false); | |||
| 17440 | switch ( element ) | |||
| 17441 | { | |||
| 17442 | case SHEET_ATK: | |||
| 17443 | break; | |||
| 17444 | case SHEET_AC: | |||
| 17445 | break; | |||
| 17446 | case SHEET_POW: | |||
| 17447 | break; | |||
| 17448 | case SHEET_RES: | |||
| 17449 | break; | |||
| 17450 | case SHEET_RGN: | |||
| 17451 | break; | |||
| 17452 | case SHEET_WGT: | |||
| 17453 | break; | |||
| 17454 | default: | |||
| 17455 | break; | |||
| 17456 | } | |||
| 17457 | entryValue->setColor(hudColors.characterSheetNeutral); | |||
| 17458 | if ( value < 0 ) | |||
| 17459 | { | |||
| 17460 | entryValue->setColor(hudColors.characterSheetRed); | |||
| 17461 | } | |||
| 17462 | else if ( value > 0 ) | |||
| 17463 | { | |||
| 17464 | entryValue->setColor(hudColors.characterSheetGreen); | |||
| 17465 | } | |||
| 17466 | entryValue->setText(valueBuf); | |||
| 17467 | entryValue->setSize(entry->getSize()); | |||
| 17468 | entryValue->setHJustify(Frame::justify_t::LEFT); | |||
| 17469 | entryValue->setVJustify(Field::justify_t::TOP); | |||
| 17470 | ||||
| 17471 | auto txtValueBackingFrame = characterSheetTooltipTextBackingFrames[player.playernum][currentTextBackingFrameIndex]; | |||
| 17472 | SDL_Rect backingFramePos = entryValue->getSize(); | |||
| 17473 | auto txtValueGet = Text::get(entryValue->getText(), entryValue->getFont(), | |||
| 17474 | entryValue->getTextColor(), entryValue->getOutlineColor()); | |||
| 17475 | longestValue = std::max(longestValue, txtValueGet->getWidth()); | |||
| 17476 | backingFramePos.x = backingFramePos.x + backingFramePos.w; | |||
| 17477 | backingFramePos.h = actualFont->height(true) + extraTextHeightForLowerCharacters - 2; | |||
| 17478 | valueSizes[currentTextBackingFrameIndex] = std::make_pair(entryValue, backingFramePos); | |||
| 17479 | txtValueBackingFrame->setDisabled(false); | |||
| 17480 | ++currentTextBackingFrameIndex; | |||
| 17481 | } | |||
| 17482 | ||||
| 17483 | if ( (element == SHEET_ATK && getAttackTooltipLines(player.playernum, attackHoverTextInfo, 4, buf, valueBuf)) | |||
| 17484 | || (element != SHEET_ATK | |||
| 17485 | && !(element == SHEET_RGN && !(svFlags & SV_FLAG_HUNGER)) | |||
| 17486 | && !(element == SHEET_RGN_MP && isInsectoidENRegen && !(svFlags & SV_FLAG_HUNGER)) | |||
| 17487 | ) | |||
| 17488 | ) | |||
| 17489 | { | |||
| 17490 | // extra number display - line 4 | |||
| 17491 | hasEntryInfoLines = true; | |||
| 17492 | currentHeight += padyMid; | |||
| 17493 | auto entry = characterSheetTooltipTextFields[player.playernum][currentTextFieldIndex]; assert(entry)(static_cast<void> (0)); | |||
| 17494 | ++currentTextFieldIndex; | |||
| 17495 | entry->setDisabled(false); | |||
| 17496 | int value = 0; | |||
| 17497 | switch ( element ) | |||
| 17498 | { | |||
| 17499 | case SHEET_ATK: | |||
| 17500 | break; | |||
| 17501 | case SHEET_AC: | |||
| 17502 | { | |||
| 17503 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_ac_entry_items_bonus").c_str()); | |||
| 17504 | Sint32 CON = statGetCON(stats[player.playernum], players[player.playernum]->entity); | |||
| 17505 | ||||
| 17506 | Sint32 oldSkillLVL = stats[player.playernum]->getProficiency(PRO_SHIELD); | |||
| 17507 | bool oldDefending = stats[player.playernum]->defending; | |||
| 17508 | stats[player.playernum]->defending = false; | |||
| 17509 | stats[player.playernum]->setProficiencyUnsafe(PRO_SHIELD, -999); | |||
| 17510 | ||||
| 17511 | Sint32 armor = AC(stats[player.playernum]); | |||
| 17512 | stats[player.playernum]->defending = oldDefending; | |||
| 17513 | stats[player.playernum]->setProficiency(PRO_SHIELD, oldSkillLVL); | |||
| 17514 | ||||
| 17515 | Sint32 itemsEffectBonus = armor - CON; | |||
| 17516 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_ac_bonus_format").c_str(), itemsEffectBonus); | |||
| 17517 | } | |||
| 17518 | break; | |||
| 17519 | case SHEET_POW: | |||
| 17520 | { | |||
| 17521 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_pwr_entry_attr_bonus").c_str()); | |||
| 17522 | std::string tag = "MAGIC_SPELLPOWER_INT"; | |||
| 17523 | std::string pwrINTBonus = formatSkillSheetEffects(player.playernum, PRO_MAGIC, tag, getHoverTextString("attributes_pwr_bonus_format")); | |||
| 17524 | snprintf(valueBuf, sizeof(valueBuf), "%s", pwrINTBonus.c_str()); | |||
| 17525 | } | |||
| 17526 | break; | |||
| 17527 | case SHEET_RES: | |||
| 17528 | { | |||
| 17529 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_res_entry_items_bonus").c_str()); | |||
| 17530 | Sint32 baseResist = 100 * damagetables[stats[player.playernum]->type][DAMAGE_TABLE_MAGIC]; | |||
| 17531 | baseResist = 100 - baseResist; | |||
| 17532 | real_t resistance = 100.0 * Entity::getDamageTableMultiplier(player.entity, *stats[player.playernum], DAMAGE_TABLE_MAGIC); | |||
| 17533 | resistance /= (Entity::getMagicResistance(stats[player.playernum]) + 1); | |||
| 17534 | resistance = (100.0 - resistance); | |||
| 17535 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_res_bonus_format").c_str(), (int)resistance - baseResist); | |||
| 17536 | } | |||
| 17537 | break; | |||
| 17538 | case SHEET_RGN: | |||
| 17539 | { | |||
| 17540 | Monster type = stats[player.playernum]->type; | |||
| 17541 | bool aestheticOnly = false; | |||
| 17542 | if ( player.entity ) | |||
| 17543 | { | |||
| 17544 | if ( player.entity->effectPolymorph == NOTHING && stats[player.playernum]->playerRace > RACE_HUMAN ) | |||
| 17545 | { | |||
| 17546 | if ( stats[player.playernum]->appearance != 0 ) | |||
| 17547 | { | |||
| 17548 | aestheticOnly = true; | |||
| 17549 | type = player.entity->getMonsterFromPlayerRace(stats[player.playernum]->playerRace); | |||
| 17550 | } | |||
| 17551 | } | |||
| 17552 | } | |||
| 17553 | real_t baseRegen = 100.0; | |||
| 17554 | if ( type == SKELETON ) | |||
| 17555 | { | |||
| 17556 | baseRegen = 25.0; | |||
| 17557 | } | |||
| 17558 | ||||
| 17559 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_entry_items_bonus").c_str()); | |||
| 17560 | real_t regen = getDisplayedHPRegen(player.entity, *stats[player.playernum], nullptr, nullptr); | |||
| 17561 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_bonus_format").c_str(), regen - baseRegen); | |||
| 17562 | } | |||
| 17563 | break; | |||
| 17564 | case SHEET_RGN_MP: | |||
| 17565 | { | |||
| 17566 | if ( isAutomatonHTRegen ) | |||
| 17567 | { | |||
| 17568 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_entry_items_bonus").c_str()); | |||
| 17569 | real_t baseHTModifier = 100.f; | |||
| 17570 | if ( stats[player.playernum]->HUNGER <= 300 ) | |||
| 17571 | { | |||
| 17572 | int baseTime = getBaseManaRegen(player.entity, *stats[player.playernum]); | |||
| 17573 | real_t scaledInterval = ((60 * baseTime) / (std::max(stats[player.playernum]->MAXMP, 1))); | |||
| 17574 | baseHTModifier = scaledInterval / TICKS_PER_SECOND50; | |||
| 17575 | baseHTModifier /= -6.0; // degrade faster | |||
| 17576 | real_t nominalRegen = MAGIC_REGEN_TIME300 / TICKS_PER_SECOND50; | |||
| 17577 | baseHTModifier = (nominalRegen / baseHTModifier) * 100.0; | |||
| 17578 | } | |||
| 17579 | else if ( stats[player.playernum]->HUNGER > 1200 ) | |||
| 17580 | { | |||
| 17581 | if ( stats[player.playernum]->MP / static_cast<real_t>(std::max(1, stats[player.playernum]->MAXMP)) <= 0.5 ) | |||
| 17582 | { | |||
| 17583 | baseHTModifier *= 4; // increase faster at < 50% mana | |||
| 17584 | } | |||
| 17585 | else | |||
| 17586 | { | |||
| 17587 | baseHTModifier *= 2; // increase less faster at > 50% mana | |||
| 17588 | } | |||
| 17589 | } | |||
| 17590 | else | |||
| 17591 | { | |||
| 17592 | // normal manaRegenInterval 300-1200 hunger. | |||
| 17593 | } | |||
| 17594 | real_t regenTotal = getDisplayedMPRegen(player.entity, *stats[player.playernum], nullptr, nullptr); | |||
| 17595 | real_t displayTotal = (regenTotal - baseHTModifier); | |||
| 17596 | //displayTotal /= 100.0; | |||
| 17597 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_ht_bonus_format").c_str(), displayTotal); | |||
| 17598 | } | |||
| 17599 | else if ( isInsectoidENRegen ) | |||
| 17600 | { | |||
| 17601 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_en_entry_items_bonus").c_str()); | |||
| 17602 | ||||
| 17603 | real_t normalRegenTime = (1000.f * 30 * 1.5) / static_cast<float>(TICKS_PER_SECOND50); // 30 base, insectoid does 1.5x in getHungerTickRate() | |||
| 17604 | normalRegenTime /= (std::max(stats[player.playernum]->MAXMP, 1)); // time for 1 mana in seconds | |||
| 17605 | normalRegenTime *= TICKS_PER_SECOND50; // game ticks for 1 mana | |||
| 17606 | ||||
| 17607 | real_t modifiedRegenTime = (1000.f * (Entity::getHungerTickRate(stats[player.playernum], true, false)) / static_cast<float>(TICKS_PER_SECOND50)); | |||
| 17608 | modifiedRegenTime /= (std::max(stats[player.playernum]->MAXMP, 1)); // time for 1 mana in seconds | |||
| 17609 | modifiedRegenTime *= TICKS_PER_SECOND50; // game ticks for 1 mana | |||
| 17610 | ||||
| 17611 | real_t baseValue = 100.0 * (normalRegenTime / modifiedRegenTime); | |||
| 17612 | real_t displayedValue = getDisplayedMPRegen(player.entity, *stats[player.playernum], nullptr, nullptr); | |||
| 17613 | ||||
| 17614 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_en_bonus_format").c_str(), displayedValue - baseValue); | |||
| 17615 | } | |||
| 17616 | else | |||
| 17617 | { | |||
| 17618 | Monster type = stats[player.playernum]->type; | |||
| 17619 | bool aestheticOnly = false; | |||
| 17620 | if ( player.entity ) | |||
| 17621 | { | |||
| 17622 | if ( player.entity->effectPolymorph == NOTHING && stats[player.playernum]->playerRace > RACE_HUMAN ) | |||
| 17623 | { | |||
| 17624 | if ( stats[player.playernum]->appearance != 0 ) | |||
| 17625 | { | |||
| 17626 | aestheticOnly = true; | |||
| 17627 | type = player.entity->getMonsterFromPlayerRace(stats[player.playernum]->playerRace); | |||
| 17628 | } | |||
| 17629 | } | |||
| 17630 | } | |||
| 17631 | real_t baseRegen = 100.0; | |||
| 17632 | if ( type == SKELETON ) | |||
| 17633 | { | |||
| 17634 | baseRegen = 25.0; | |||
| 17635 | } | |||
| 17636 | ||||
| 17637 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_entry_items_bonus").c_str()); | |||
| 17638 | Sint32 oldINT = stats[player.playernum]->INT; | |||
| 17639 | stats[player.playernum]->INT += -statGetINT(stats[player.playernum], player.entity); | |||
| 17640 | real_t regenWithoutINT = getDisplayedMPRegen(player.entity, *stats[player.playernum], nullptr, nullptr); | |||
| 17641 | stats[player.playernum]->INT = oldINT; | |||
| 17642 | real_t regenTotal = getDisplayedMPRegen(player.entity, *stats[player.playernum], nullptr, nullptr); | |||
| 17643 | real_t regenStatSkill = regenTotal - regenWithoutINT; | |||
| 17644 | ||||
| 17645 | real_t regenItemsEffects = regenTotal - regenStatSkill - baseRegen; | |||
| 17646 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_bonus_format").c_str(), regenItemsEffects); | |||
| 17647 | } | |||
| 17648 | } | |||
| 17649 | break; | |||
| 17650 | case SHEET_WGT: | |||
| 17651 | { | |||
| 17652 | int weight = player.movement.getCharacterModifiedWeight(); | |||
| 17653 | int equippedWeightTotal = player.movement.getCharacterEquippedWeight(); | |||
| 17654 | int equippedWeight = player.movement.getCharacterModifiedWeight(&equippedWeightTotal); | |||
| 17655 | Sint32 STR = statGetSTR(stats[player.playernum], player.entity); | |||
| 17656 | Sint32 DEX = statGetDEX(stats[player.playernum], player.entity); | |||
| 17657 | real_t currentEquippedSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(equippedWeight, STR), DEX); | |||
| 17658 | //real_t currentSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(weight, STR), DEX); | |||
| 17659 | real_t noWeightSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(0, STR), DEX); | |||
| 17660 | real_t maxSpeed = player.movement.getMaximumSpeed(); | |||
| 17661 | ||||
| 17662 | //real_t currentSpeedPercent = 100.0 * currentSpeed / std::fmax(.01, maxSpeed); | |||
| 17663 | real_t currentEquippedSpeedPercent = 100.0 * currentEquippedSpeed / std::fmax(.01, maxSpeed); | |||
| 17664 | real_t noWeightSpeedPercent = 100.0 * noWeightSpeed / std::fmax(.01, maxSpeed); | |||
| 17665 | ||||
| 17666 | real_t displayValue = (currentEquippedSpeedPercent - noWeightSpeedPercent); | |||
| 17667 | if ( displayValue >= 0.0 ) | |||
| 17668 | { | |||
| 17669 | displayValue = -.000001; // so there is a negative sign | |||
| 17670 | } | |||
| 17671 | ||||
| 17672 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_wgt_equipment_value").c_str()); | |||
| 17673 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_wgt_speed_bonus_format").c_str(), | |||
| 17674 | displayValue); | |||
| 17675 | } | |||
| 17676 | break; | |||
| 17677 | default: | |||
| 17678 | break; | |||
| 17679 | } | |||
| 17680 | entry->setText(buf); | |||
| 17681 | entry->setVJustify(Field::justify_t::TOP); | |||
| 17682 | ||||
| 17683 | SDL_Rect entryPos = entry->getSize(); | |||
| 17684 | entryPos.x = padx + padxMid; | |||
| 17685 | entryPos.y = currentHeight; | |||
| 17686 | entryPos.w = txtPos.w - (padxMid * 2); | |||
| 17687 | entry->setSize(entryPos); | |||
| 17688 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry4 != entry->getText() ) | |||
| 17689 | { | |||
| 17690 | entry->reflowTextToFit(0); | |||
| 17691 | charsheetTooltipCache[player.playernum].textEntries[element].entry4 = entry->getText(); | |||
| 17692 | } | |||
| 17693 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 17694 | entry->setSize(entryPos); | |||
| 17695 | entry->setColor(defaultColor); | |||
| 17696 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 17697 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 17698 | ||||
| 17699 | auto entryValue = characterSheetTooltipTextFields[player.playernum][currentTextFieldIndex]; assert(entry)(static_cast<void> (0)); | |||
| 17700 | ++currentTextFieldIndex; | |||
| 17701 | entryValue->setDisabled(false); | |||
| 17702 | switch ( element ) | |||
| 17703 | { | |||
| 17704 | case SHEET_ATK: | |||
| 17705 | break; | |||
| 17706 | case SHEET_AC: | |||
| 17707 | break; | |||
| 17708 | case SHEET_POW: | |||
| 17709 | break; | |||
| 17710 | case SHEET_RES: | |||
| 17711 | break; | |||
| 17712 | case SHEET_RGN: | |||
| 17713 | break; | |||
| 17714 | case SHEET_WGT: | |||
| 17715 | break; | |||
| 17716 | default: | |||
| 17717 | break; | |||
| 17718 | } | |||
| 17719 | entryValue->setColor(hudColors.characterSheetNeutral); | |||
| 17720 | if ( value < 0 ) | |||
| 17721 | { | |||
| 17722 | entryValue->setColor(hudColors.characterSheetRed); | |||
| 17723 | } | |||
| 17724 | else if ( value > 0 ) | |||
| 17725 | { | |||
| 17726 | entryValue->setColor(hudColors.characterSheetGreen); | |||
| 17727 | } | |||
| 17728 | entryValue->setText(valueBuf); | |||
| 17729 | entryValue->setSize(entry->getSize()); | |||
| 17730 | entryValue->setHJustify(Frame::justify_t::LEFT); | |||
| 17731 | entryValue->setVJustify(Field::justify_t::TOP); | |||
| 17732 | ||||
| 17733 | auto txtValueBackingFrame = characterSheetTooltipTextBackingFrames[player.playernum][currentTextBackingFrameIndex]; | |||
| 17734 | SDL_Rect backingFramePos = entryValue->getSize(); | |||
| 17735 | auto txtValueGet = Text::get(entryValue->getText(), entryValue->getFont(), | |||
| 17736 | entryValue->getTextColor(), entryValue->getOutlineColor()); | |||
| 17737 | longestValue = std::max(longestValue, txtValueGet->getWidth()); | |||
| 17738 | backingFramePos.x = backingFramePos.x + backingFramePos.w; | |||
| 17739 | backingFramePos.h = actualFont->height(true) + extraTextHeightForLowerCharacters - 2; | |||
| 17740 | valueSizes[4] = std::make_pair(entryValue, backingFramePos); | |||
| 17741 | txtValueBackingFrame->setDisabled(false); | |||
| 17742 | ++currentTextBackingFrameIndex; | |||
| 17743 | } | |||
| 17744 | ||||
| 17745 | if ( element == SHEET_ATK && getAttackTooltipLines(player.playernum, attackHoverTextInfo, 5, buf, valueBuf) | |||
| 17746 | || (element != SHEET_ATK | |||
| 17747 | && element != SHEET_RES | |||
| 17748 | && !(element == SHEET_RGN && !(svFlags & SV_FLAG_HUNGER)) | |||
| 17749 | && !(element == SHEET_RGN_MP && isInsectoidENRegen && !(svFlags & SV_FLAG_HUNGER)) | |||
| 17750 | ) | |||
| 17751 | ) | |||
| 17752 | { | |||
| 17753 | // extra number display - line 5 | |||
| 17754 | hasEntryInfoLines = true; | |||
| 17755 | currentHeight += padyMid; | |||
| 17756 | auto entry = characterSheetTooltipTextFields[player.playernum][currentTextFieldIndex]; assert(entry)(static_cast<void> (0)); | |||
| 17757 | ++currentTextFieldIndex; | |||
| 17758 | entry->setDisabled(false); | |||
| 17759 | int value = 0; | |||
| 17760 | switch ( element ) | |||
| 17761 | { | |||
| 17762 | case SHEET_ATK: | |||
| 17763 | break; | |||
| 17764 | case SHEET_AC: | |||
| 17765 | { | |||
| 17766 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_ac_passive_bonus").c_str()); | |||
| 17767 | ||||
| 17768 | Sint32 oldSkillLVL = stats[player.playernum]->getProficiency(PRO_SHIELD); | |||
| 17769 | bool oldDefending = stats[player.playernum]->defending; | |||
| 17770 | stats[player.playernum]->defending = false; | |||
| 17771 | ||||
| 17772 | Sint32 armor = AC(stats[player.playernum]); | |||
| 17773 | stats[player.playernum]->setProficiencyUnsafe(PRO_SHIELD, -999); | |||
| 17774 | Sint32 armorNoSkill = AC(stats[player.playernum]); | |||
| 17775 | stats[player.playernum]->setProficiency(PRO_SHIELD, oldSkillLVL); | |||
| 17776 | stats[player.playernum]->defending = oldDefending; | |||
| 17777 | ||||
| 17778 | Sint32 passiveBonus = armor - armorNoSkill; | |||
| 17779 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_ac_bonus_format").c_str(), passiveBonus); | |||
| 17780 | } | |||
| 17781 | break; | |||
| 17782 | case SHEET_POW: | |||
| 17783 | { | |||
| 17784 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_pwr_entry_items_bonus").c_str()); | |||
| 17785 | std::string tag = "MAGIC_SPELLPOWER_EQUIPMENT"; | |||
| 17786 | std::string pwrINTBonus = formatSkillSheetEffects(player.playernum, PRO_MAGIC, tag, getHoverTextString("attributes_pwr_bonus_format")); | |||
| 17787 | snprintf(valueBuf, sizeof(valueBuf), "%s", pwrINTBonus.c_str()); | |||
| 17788 | } | |||
| 17789 | break; | |||
| 17790 | case SHEET_RES: | |||
| 17791 | break; | |||
| 17792 | case SHEET_RGN: | |||
| 17793 | { | |||
| 17794 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_plain_display").c_str()); | |||
| 17795 | real_t regen = (static_cast<real_t>(Entity::getHealthRegenInterval(player.entity, *stats[player.playernum], true)) / TICKS_PER_SECOND50); | |||
| 17796 | if ( regen <= 0.0 ) | |||
| 17797 | { | |||
| 17798 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_hp_per_second_format_zero").c_str(), | |||
| 17799 | (static_cast<real_t>(HEAL_TIME600) / TICKS_PER_SECOND50)); | |||
| 17800 | } | |||
| 17801 | else | |||
| 17802 | { | |||
| 17803 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_hp_per_second_format").c_str(), | |||
| 17804 | regen); | |||
| 17805 | } | |||
| 17806 | } | |||
| 17807 | break; | |||
| 17808 | case SHEET_RGN_MP: | |||
| 17809 | { | |||
| 17810 | if ( isAutomatonHTRegen ) | |||
| 17811 | { | |||
| 17812 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_ht_boiler_status").c_str()); | |||
| 17813 | if ( stats[player.playernum]->HUNGER <= 300 ) | |||
| 17814 | { | |||
| 17815 | value = -1; | |||
| 17816 | snprintf(valueBuf, sizeof(valueBuf), "%s", getHoverTextString("attributes_rgn_ht_boiler_value_low").c_str()); | |||
| 17817 | } | |||
| 17818 | else if ( stats[player.playernum]->HUNGER > 1200 ) | |||
| 17819 | { | |||
| 17820 | value = 2; | |||
| 17821 | snprintf(valueBuf, sizeof(valueBuf), "%s", getHoverTextString("attributes_rgn_ht_boiler_value_superheat").c_str()); | |||
| 17822 | } | |||
| 17823 | else | |||
| 17824 | { | |||
| 17825 | value = 1; | |||
| 17826 | snprintf(valueBuf, sizeof(valueBuf), "%s", getHoverTextString("attributes_rgn_ht_boiler_value_normal").c_str()); | |||
| 17827 | } | |||
| 17828 | } | |||
| 17829 | else if ( isInsectoidENRegen ) | |||
| 17830 | { | |||
| 17831 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_plain_display").c_str()); | |||
| 17832 | real_t regen = (static_cast<real_t>(Entity::getManaRegenInterval(player.entity, *stats[player.playernum], true)) / TICKS_PER_SECOND50); | |||
| 17833 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_en_per_second_format").c_str(), regen); | |||
| 17834 | } | |||
| 17835 | else | |||
| 17836 | { | |||
| 17837 | Monster type = stats[player.playernum]->type; | |||
| 17838 | bool aestheticOnly = false; | |||
| 17839 | if ( player.entity ) | |||
| 17840 | { | |||
| 17841 | if ( player.entity->effectPolymorph == NOTHING && stats[player.playernum]->playerRace > RACE_HUMAN ) | |||
| 17842 | { | |||
| 17843 | if ( stats[player.playernum]->appearance != 0 ) | |||
| 17844 | { | |||
| 17845 | aestheticOnly = true; | |||
| 17846 | type = player.entity->getMonsterFromPlayerRace(stats[player.playernum]->playerRace); | |||
| 17847 | } | |||
| 17848 | } | |||
| 17849 | } | |||
| 17850 | real_t baseRegen = 100.0; | |||
| 17851 | if ( type == SKELETON ) | |||
| 17852 | { | |||
| 17853 | baseRegen = 25.0; | |||
| 17854 | } | |||
| 17855 | ||||
| 17856 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_entry_statskill_bonus").c_str()); | |||
| 17857 | Sint32 oldINT = stats[player.playernum]->INT; | |||
| 17858 | stats[player.playernum]->INT += -statGetINT(stats[player.playernum], player.entity); | |||
| 17859 | real_t regenWithoutINT = getDisplayedMPRegen(player.entity, *stats[player.playernum], nullptr, nullptr); | |||
| 17860 | stats[player.playernum]->INT = oldINT; | |||
| 17861 | ||||
| 17862 | real_t regenTotal = getDisplayedMPRegen(player.entity, *stats[player.playernum], nullptr, nullptr); | |||
| 17863 | real_t regenStatSkill = regenTotal - regenWithoutINT; | |||
| 17864 | ||||
| 17865 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_bonus_format").c_str(), regenStatSkill); | |||
| 17866 | } | |||
| 17867 | } | |||
| 17868 | break; | |||
| 17869 | case SHEET_WGT: | |||
| 17870 | { | |||
| 17871 | int weight = player.movement.getCharacterModifiedWeight(); | |||
| 17872 | int equippedWeightTotal = player.movement.getCharacterEquippedWeight(); | |||
| 17873 | int equippedWeight = player.movement.getCharacterModifiedWeight(&equippedWeightTotal); | |||
| 17874 | int goldWeightTotal = stats[player.playernum]->getGoldWeight(); | |||
| 17875 | int goldWeight = player.movement.getCharacterModifiedWeight(&goldWeightTotal); | |||
| 17876 | Sint32 STR = statGetSTR(stats[player.playernum], player.entity); | |||
| 17877 | Sint32 DEX = statGetDEX(stats[player.playernum], player.entity); | |||
| 17878 | real_t currentEquippedSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(equippedWeight, STR), DEX); | |||
| 17879 | real_t currentSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(weight - goldWeight, STR), DEX); // ignore gold | |||
| 17880 | real_t noWeightSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(0, STR), DEX); | |||
| 17881 | real_t maxSpeed = player.movement.getMaximumSpeed(); | |||
| 17882 | ||||
| 17883 | real_t currentSpeedPercent = 100.0 * currentSpeed / std::fmax(.01, maxSpeed); | |||
| 17884 | real_t currentEquippedSpeedPercent = 100.0 * currentEquippedSpeed / std::fmax(.01, maxSpeed); | |||
| 17885 | real_t noWeightSpeedPercent = 100.0 * noWeightSpeed / std::fmax(.01, maxSpeed); | |||
| 17886 | ||||
| 17887 | real_t displayValue = (currentSpeedPercent - noWeightSpeedPercent) | |||
| 17888 | - (currentEquippedSpeedPercent - noWeightSpeedPercent); | |||
| 17889 | if ( displayValue >= 0.0 ) | |||
| 17890 | { | |||
| 17891 | displayValue = -.000001; // so there is a negative sign | |||
| 17892 | } | |||
| 17893 | ||||
| 17894 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_wgt_inventory_value").c_str()); | |||
| 17895 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_wgt_speed_bonus_format").c_str(), | |||
| 17896 | displayValue); | |||
| 17897 | } | |||
| 17898 | break; | |||
| 17899 | default: | |||
| 17900 | break; | |||
| 17901 | } | |||
| 17902 | entry->setText(buf); | |||
| 17903 | entry->setVJustify(Field::justify_t::TOP); | |||
| 17904 | ||||
| 17905 | SDL_Rect entryPos = entry->getSize(); | |||
| 17906 | entryPos.x = padx + padxMid; | |||
| 17907 | entryPos.y = currentHeight; | |||
| 17908 | entryPos.w = txtPos.w - (padxMid * 2); | |||
| 17909 | entry->setSize(entryPos); | |||
| 17910 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry5 != entry->getText() ) | |||
| 17911 | { | |||
| 17912 | entry->reflowTextToFit(0); | |||
| 17913 | charsheetTooltipCache[player.playernum].textEntries[element].entry5 = entry->getText(); | |||
| 17914 | } | |||
| 17915 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 17916 | entry->setSize(entryPos); | |||
| 17917 | entry->setColor(defaultColor); | |||
| 17918 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 17919 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 17920 | ||||
| 17921 | auto entryValue = characterSheetTooltipTextFields[player.playernum][currentTextFieldIndex]; assert(entry)(static_cast<void> (0)); | |||
| 17922 | ++currentTextFieldIndex; | |||
| 17923 | entryValue->setDisabled(false); | |||
| 17924 | switch ( element ) | |||
| 17925 | { | |||
| 17926 | case SHEET_ATK: | |||
| 17927 | break; | |||
| 17928 | case SHEET_AC: | |||
| 17929 | break; | |||
| 17930 | case SHEET_POW: | |||
| 17931 | break; | |||
| 17932 | case SHEET_RES: | |||
| 17933 | break; | |||
| 17934 | case SHEET_RGN: | |||
| 17935 | break; | |||
| 17936 | case SHEET_WGT: | |||
| 17937 | break; | |||
| 17938 | default: | |||
| 17939 | break; | |||
| 17940 | } | |||
| 17941 | entryValue->setColor(hudColors.characterSheetNeutral); | |||
| 17942 | if ( value < 0 ) | |||
| 17943 | { | |||
| 17944 | entryValue->setColor(hudColors.characterSheetRed); | |||
| 17945 | } | |||
| 17946 | else if ( value > 0 ) | |||
| 17947 | { | |||
| 17948 | if ( isAutomatonHTRegen ) | |||
| 17949 | { | |||
| 17950 | if ( value == 2 ) // supercharge | |||
| 17951 | { | |||
| 17952 | entryValue->setColor(hudColors.characterSheetHeadingText); | |||
| 17953 | } | |||
| 17954 | else | |||
| 17955 | { | |||
| 17956 | entryValue->setColor(hudColors.characterSheetGreen); | |||
| 17957 | } | |||
| 17958 | } | |||
| 17959 | else | |||
| 17960 | { | |||
| 17961 | entryValue->setColor(hudColors.characterSheetGreen); | |||
| 17962 | } | |||
| 17963 | } | |||
| 17964 | entryValue->setText(valueBuf); | |||
| 17965 | entryValue->setSize(entry->getSize()); | |||
| 17966 | entryValue->setHJustify(Frame::justify_t::LEFT); | |||
| 17967 | entryValue->setVJustify(Field::justify_t::TOP); | |||
| 17968 | ||||
| 17969 | if ( element == SHEET_RGN || (element == SHEET_RGN_MP && (isAutomatonHTRegen || isInsectoidENRegen)) ) | |||
| 17970 | { | |||
| 17971 | // special rule here to ignore size of this long line | |||
| 17972 | auto txtValueBackingFrame = characterSheetTooltipTextBackingFrames[player.playernum][currentTextBackingFrameIndex]; | |||
| 17973 | SDL_Rect backingFramePos = entryValue->getSize(); | |||
| 17974 | auto txtValueGet = Text::get(entryValue->getText(), entryValue->getFont(), | |||
| 17975 | entryValue->getTextColor(), entryValue->getOutlineColor()); | |||
| 17976 | //longestValue = std::max(longestValue, txtValueGet->getWidth()); | |||
| 17977 | backingFramePos.x = backingFramePos.x + backingFramePos.w; | |||
| 17978 | backingFramePos.h = actualFont->height(true) + extraTextHeightForLowerCharacters - 2; | |||
| 17979 | //valueSizes[currentTextBackingFrameIndex] = std::make_pair(entryValue, backingFramePos); | |||
| 17980 | txtValueBackingFrame->setDisabled(true); | |||
| 17981 | ||||
| 17982 | backingFramePos.w = (int)txtValueGet->getWidth(); | |||
| 17983 | backingFramePos.x -= backingFramePos.w; | |||
| 17984 | backingFramePos.x -= 8; | |||
| 17985 | entryValue->setSize(backingFramePos); | |||
| 17986 | ++currentTextBackingFrameIndex; | |||
| 17987 | } | |||
| 17988 | else | |||
| 17989 | { | |||
| 17990 | auto txtValueBackingFrame = characterSheetTooltipTextBackingFrames[player.playernum][currentTextBackingFrameIndex]; | |||
| 17991 | SDL_Rect backingFramePos = entryValue->getSize(); | |||
| 17992 | auto txtValueGet = Text::get(entryValue->getText(), entryValue->getFont(), | |||
| 17993 | entryValue->getTextColor(), entryValue->getOutlineColor()); | |||
| 17994 | longestValue = std::max(longestValue, txtValueGet->getWidth()); | |||
| 17995 | backingFramePos.x = backingFramePos.x + backingFramePos.w; | |||
| 17996 | backingFramePos.h = actualFont->height(true) + extraTextHeightForLowerCharacters - 2; | |||
| 17997 | valueSizes[currentTextBackingFrameIndex] = std::make_pair(entryValue, backingFramePos); | |||
| 17998 | txtValueBackingFrame->setDisabled(false); | |||
| 17999 | ++currentTextBackingFrameIndex; | |||
| 18000 | } | |||
| 18001 | } | |||
| 18002 | ||||
| 18003 | if ( element == SHEET_ATK && getAttackTooltipLines(player.playernum, attackHoverTextInfo, 6, buf, valueBuf) | |||
| 18004 | || (element == SHEET_RGN_MP && !isInsectoidENRegen) || element == SHEET_WGT ) | |||
| 18005 | { | |||
| 18006 | // extra number display - line 6 | |||
| 18007 | hasEntryInfoLines = true; | |||
| 18008 | currentHeight += padyMid; | |||
| 18009 | auto entry = characterSheetTooltipTextFields[player.playernum][currentTextFieldIndex]; assert(entry)(static_cast<void> (0)); | |||
| 18010 | ++currentTextFieldIndex; | |||
| 18011 | entry->setDisabled(false); | |||
| 18012 | switch ( element ) | |||
| 18013 | { | |||
| 18014 | case SHEET_ATK: | |||
| 18015 | break; | |||
| 18016 | case SHEET_AC: | |||
| 18017 | break; | |||
| 18018 | case SHEET_POW: | |||
| 18019 | break; | |||
| 18020 | case SHEET_RES: | |||
| 18021 | break; | |||
| 18022 | case SHEET_RGN_MP: | |||
| 18023 | { | |||
| 18024 | if ( isAutomatonHTRegen ) | |||
| 18025 | { | |||
| 18026 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_plain_display").c_str()); | |||
| 18027 | real_t regen = (static_cast<real_t>(Entity::getManaRegenInterval(player.entity, *stats[player.playernum], true)) / TICKS_PER_SECOND50); | |||
| 18028 | if ( stats[player.playernum]->HUNGER <= 300 ) | |||
| 18029 | { | |||
| 18030 | regen /= 6; // degrade faster | |||
| 18031 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_ht_per_second_format").c_str(), -1, regen); | |||
| 18032 | } | |||
| 18033 | else if ( stats[player.playernum]->HUNGER > 1200 ) | |||
| 18034 | { | |||
| 18035 | if ( stats[player.playernum]->MP / static_cast<real_t>(std::max(1, stats[player.playernum]->MAXMP)) <= 0.5 ) | |||
| 18036 | { | |||
| 18037 | regen /= 4; // increase faster at < 50% mana | |||
| 18038 | } | |||
| 18039 | else | |||
| 18040 | { | |||
| 18041 | regen /= 2; // increase less faster at > 50% mana | |||
| 18042 | } | |||
| 18043 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_ht_per_second_format").c_str(), 1, regen); | |||
| 18044 | } | |||
| 18045 | else if ( stats[player.playernum]->HUNGER > 300 ) | |||
| 18046 | { | |||
| 18047 | // normal manaRegenInterval 300-1200 hunger. | |||
| 18048 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_ht_per_second_format").c_str(), 1, regen); | |||
| 18049 | } | |||
| 18050 | } | |||
| 18051 | else | |||
| 18052 | { | |||
| 18053 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_rgn_plain_display").c_str()); | |||
| 18054 | real_t regen = (static_cast<real_t>(Entity::getManaRegenInterval(player.entity, *stats[player.playernum], true)) / TICKS_PER_SECOND50); | |||
| 18055 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_rgn_mp_per_second_format").c_str(), regen); | |||
| 18056 | } | |||
| 18057 | } | |||
| 18058 | break; | |||
| 18059 | case SHEET_WGT: | |||
| 18060 | { | |||
| 18061 | int weight = player.movement.getCharacterModifiedWeight(); | |||
| 18062 | int equippedWeightTotal = player.movement.getCharacterEquippedWeight(); | |||
| 18063 | int equippedWeight = player.movement.getCharacterModifiedWeight(&equippedWeightTotal); | |||
| 18064 | int goldWeightTotal = stats[player.playernum]->getGoldWeight(); | |||
| 18065 | int goldWeight = player.movement.getCharacterModifiedWeight(&goldWeightTotal); | |||
| 18066 | Sint32 STR = statGetSTR(stats[player.playernum], player.entity); | |||
| 18067 | Sint32 DEX = statGetDEX(stats[player.playernum], player.entity); | |||
| 18068 | //real_t currentEquippedSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(equippedWeight, STR), DEX); | |||
| 18069 | real_t currentSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(weight, STR), DEX); | |||
| 18070 | real_t noWeightSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(0, STR), DEX); | |||
| 18071 | //real_t goldSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(goldWeight, STR), DEX); | |||
| 18072 | real_t noGoldSpeed = player.movement.getSpeedFactor(player.movement.getWeightRatio(weight - goldWeight, STR), DEX); | |||
| 18073 | real_t maxSpeed = player.movement.getMaximumSpeed(); | |||
| 18074 | ||||
| 18075 | real_t currentSpeedPercent = 100.0 * currentSpeed / std::fmax(.01, maxSpeed); | |||
| 18076 | //real_t currentEquippedSpeedPercent = 100.0 * currentEquippedSpeed / std::fmax(.01, maxSpeed); | |||
| 18077 | real_t noWeightSpeedPercent = 100.0 * noWeightSpeed / std::fmax(.01, maxSpeed); | |||
| 18078 | //real_t goldSpeedPercent = 100.0 * goldSpeed / std::fmax(.01, maxSpeed); | |||
| 18079 | real_t noGoldSpeedPercent = 100.0 * noGoldSpeed / std::fmax(.01, maxSpeed); | |||
| 18080 | ||||
| 18081 | real_t displayValue = (currentSpeedPercent - noWeightSpeedPercent) | |||
| 18082 | - (noGoldSpeedPercent - noWeightSpeedPercent); | |||
| 18083 | if ( displayValue >= 0.001 ) | |||
| 18084 | { | |||
| 18085 | // do nothing | |||
| 18086 | } | |||
| 18087 | else if ( displayValue >= 0.0 ) | |||
| 18088 | { | |||
| 18089 | displayValue = -.000001; // so there is a negative sign | |||
| 18090 | } | |||
| 18091 | ||||
| 18092 | snprintf(buf, sizeof(buf), "%s", getHoverTextString("attributes_wgt_gold_value").c_str()); | |||
| 18093 | snprintf(valueBuf, sizeof(valueBuf), getHoverTextString("attributes_wgt_speed_bonus_format").c_str(), | |||
| 18094 | displayValue); | |||
| 18095 | } | |||
| 18096 | break; | |||
| 18097 | default: | |||
| 18098 | break; | |||
| 18099 | } | |||
| 18100 | entry->setText(buf); | |||
| 18101 | entry->setVJustify(Field::justify_t::TOP); | |||
| 18102 | ||||
| 18103 | SDL_Rect entryPos = entry->getSize(); | |||
| 18104 | entryPos.x = padx + padxMid; | |||
| 18105 | entryPos.y = currentHeight; | |||
| 18106 | entryPos.w = txtPos.w - (padxMid * 2); | |||
| 18107 | entry->setSize(entryPos); | |||
| 18108 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry6 != entry->getText() ) | |||
| 18109 | { | |||
| 18110 | entry->reflowTextToFit(0); | |||
| 18111 | charsheetTooltipCache[player.playernum].textEntries[element].entry6 = entry->getText(); | |||
| 18112 | } | |||
| 18113 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 18114 | entry->setSize(entryPos); | |||
| 18115 | entry->setColor(defaultColor); | |||
| 18116 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 18117 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 18118 | ||||
| 18119 | auto entryValue = characterSheetTooltipTextFields[player.playernum][currentTextFieldIndex]; assert(entry)(static_cast<void> (0)); | |||
| 18120 | ++currentTextFieldIndex; | |||
| 18121 | entryValue->setDisabled(false); | |||
| 18122 | int value = 0; | |||
| 18123 | switch ( element ) | |||
| 18124 | { | |||
| 18125 | case SHEET_ATK: | |||
| 18126 | break; | |||
| 18127 | case SHEET_AC: | |||
| 18128 | break; | |||
| 18129 | case SHEET_POW: | |||
| 18130 | break; | |||
| 18131 | case SHEET_RES: | |||
| 18132 | break; | |||
| 18133 | case SHEET_RGN: | |||
| 18134 | break; | |||
| 18135 | case SHEET_WGT: | |||
| 18136 | break; | |||
| 18137 | default: | |||
| 18138 | break; | |||
| 18139 | } | |||
| 18140 | entryValue->setColor(hudColors.characterSheetNeutral); | |||
| 18141 | if ( value < 0 ) | |||
| 18142 | { | |||
| 18143 | entryValue->setColor(hudColors.characterSheetRed); | |||
| 18144 | } | |||
| 18145 | else if ( value > 0 ) | |||
| 18146 | { | |||
| 18147 | entryValue->setColor(hudColors.characterSheetGreen); | |||
| 18148 | } | |||
| 18149 | entryValue->setText(valueBuf); | |||
| 18150 | entryValue->setSize(entry->getSize()); | |||
| 18151 | entryValue->setHJustify(Frame::justify_t::LEFT); | |||
| 18152 | entryValue->setVJustify(Field::justify_t::TOP); | |||
| 18153 | ||||
| 18154 | if ( element == SHEET_RGN_MP ) | |||
| 18155 | { | |||
| 18156 | // special rule here to ignore size of this long line | |||
| 18157 | auto txtValueBackingFrame = characterSheetTooltipTextBackingFrames[player.playernum][currentTextBackingFrameIndex]; | |||
| 18158 | SDL_Rect backingFramePos = entryValue->getSize(); | |||
| 18159 | auto txtValueGet = Text::get(entryValue->getText(), entryValue->getFont(), | |||
| 18160 | entryValue->getTextColor(), entryValue->getOutlineColor()); | |||
| 18161 | //longestValue = std::max(longestValue, txtValueGet->getWidth()); | |||
| 18162 | backingFramePos.x = backingFramePos.x + backingFramePos.w; | |||
| 18163 | backingFramePos.h = actualFont->height(true) + extraTextHeightForLowerCharacters - 2; | |||
| 18164 | //valueSizes[currentTextBackingFrameIndex] = std::make_pair(entryValue, backingFramePos); | |||
| 18165 | txtValueBackingFrame->setDisabled(true); | |||
| 18166 | ||||
| 18167 | backingFramePos.w = (int)txtValueGet->getWidth(); | |||
| 18168 | backingFramePos.x -= backingFramePos.w; | |||
| 18169 | backingFramePos.x -= 8; | |||
| 18170 | entryValue->setSize(backingFramePos); | |||
| 18171 | ++currentTextBackingFrameIndex; | |||
| 18172 | } | |||
| 18173 | else | |||
| 18174 | { | |||
| 18175 | auto txtValueBackingFrame = characterSheetTooltipTextBackingFrames[player.playernum][currentTextBackingFrameIndex]; | |||
| 18176 | SDL_Rect backingFramePos = entryValue->getSize(); | |||
| 18177 | auto txtValueGet = Text::get(entryValue->getText(), entryValue->getFont(), | |||
| 18178 | entryValue->getTextColor(), entryValue->getOutlineColor()); | |||
| 18179 | longestValue = std::max(longestValue, txtValueGet->getWidth()); | |||
| 18180 | backingFramePos.x = backingFramePos.x + backingFramePos.w; | |||
| 18181 | backingFramePos.h = actualFont->height(true) + extraTextHeightForLowerCharacters - 2; | |||
| 18182 | valueSizes[currentTextBackingFrameIndex] = std::make_pair(entryValue, backingFramePos); | |||
| 18183 | txtValueBackingFrame->setDisabled(false); | |||
| 18184 | ++currentTextBackingFrameIndex; | |||
| 18185 | } | |||
| 18186 | } | |||
| 18187 | ||||
| 18188 | if ( element == SHEET_ATK && getAttackTooltipLines(player.playernum, attackHoverTextInfo, 7, buf, valueBuf) ) | |||
| 18189 | { | |||
| 18190 | // extra number display - line 7 | |||
| 18191 | hasEntryInfoLines = true; | |||
| 18192 | currentHeight += padyMid; | |||
| 18193 | auto entry = characterSheetTooltipTextFields[player.playernum][currentTextFieldIndex]; assert(entry)(static_cast<void> (0)); | |||
| 18194 | ++currentTextFieldIndex; | |||
| 18195 | entry->setDisabled(false); | |||
| 18196 | switch ( element ) | |||
| 18197 | { | |||
| 18198 | case SHEET_ATK: | |||
| 18199 | break; | |||
| 18200 | case SHEET_AC: | |||
| 18201 | break; | |||
| 18202 | case SHEET_POW: | |||
| 18203 | break; | |||
| 18204 | case SHEET_RES: | |||
| 18205 | break; | |||
| 18206 | case SHEET_RGN: | |||
| 18207 | break; | |||
| 18208 | case SHEET_WGT: | |||
| 18209 | break; | |||
| 18210 | default: | |||
| 18211 | break; | |||
| 18212 | } | |||
| 18213 | entry->setText(buf); | |||
| 18214 | entry->setVJustify(Field::justify_t::TOP); | |||
| 18215 | ||||
| 18216 | SDL_Rect entryPos = entry->getSize(); | |||
| 18217 | entryPos.x = padx + padxMid; | |||
| 18218 | entryPos.y = currentHeight; | |||
| 18219 | entryPos.w = txtPos.w - (padxMid * 2); | |||
| 18220 | entry->setSize(entryPos); | |||
| 18221 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry7 != entry->getText() ) | |||
| 18222 | { | |||
| 18223 | entry->reflowTextToFit(0); | |||
| 18224 | charsheetTooltipCache[player.playernum].textEntries[element].entry7 = entry->getText(); | |||
| 18225 | } | |||
| 18226 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 18227 | entry->setSize(entryPos); | |||
| 18228 | entry->setColor(defaultColor); | |||
| 18229 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 18230 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 18231 | ||||
| 18232 | auto entryValue = characterSheetTooltipTextFields[player.playernum][currentTextFieldIndex]; assert(entry)(static_cast<void> (0)); | |||
| 18233 | ++currentTextFieldIndex; | |||
| 18234 | entryValue->setDisabled(false); | |||
| 18235 | int value = 0; | |||
| 18236 | switch ( element ) | |||
| 18237 | { | |||
| 18238 | case SHEET_ATK: | |||
| 18239 | break; | |||
| 18240 | case SHEET_AC: | |||
| 18241 | break; | |||
| 18242 | case SHEET_POW: | |||
| 18243 | break; | |||
| 18244 | case SHEET_RES: | |||
| 18245 | break; | |||
| 18246 | case SHEET_RGN: | |||
| 18247 | break; | |||
| 18248 | case SHEET_WGT: | |||
| 18249 | break; | |||
| 18250 | default: | |||
| 18251 | break; | |||
| 18252 | } | |||
| 18253 | entryValue->setColor(hudColors.characterSheetNeutral); | |||
| 18254 | if ( value < 0 ) | |||
| 18255 | { | |||
| 18256 | entryValue->setColor(hudColors.characterSheetRed); | |||
| 18257 | } | |||
| 18258 | else if ( value > 0 ) | |||
| 18259 | { | |||
| 18260 | entryValue->setColor(hudColors.characterSheetGreen); | |||
| 18261 | } | |||
| 18262 | entryValue->setText(valueBuf); | |||
| 18263 | entryValue->setSize(entry->getSize()); | |||
| 18264 | entryValue->setHJustify(Frame::justify_t::LEFT); | |||
| 18265 | entryValue->setVJustify(Field::justify_t::TOP); | |||
| 18266 | ||||
| 18267 | auto txtValueBackingFrame = characterSheetTooltipTextBackingFrames[player.playernum][currentTextBackingFrameIndex]; | |||
| 18268 | SDL_Rect backingFramePos = entryValue->getSize(); | |||
| 18269 | auto txtValueGet = Text::get(entryValue->getText(), entryValue->getFont(), | |||
| 18270 | entryValue->getTextColor(), entryValue->getOutlineColor()); | |||
| 18271 | longestValue = std::max(longestValue, txtValueGet->getWidth()); | |||
| 18272 | backingFramePos.x = backingFramePos.x + backingFramePos.w; | |||
| 18273 | backingFramePos.h = actualFont->height(true) + extraTextHeightForLowerCharacters - 2; | |||
| 18274 | valueSizes[currentTextBackingFrameIndex] = std::make_pair(entryValue, backingFramePos); | |||
| 18275 | txtValueBackingFrame->setDisabled(false); | |||
| 18276 | ++currentTextBackingFrameIndex; | |||
| 18277 | } | |||
| 18278 | ||||
| 18279 | for ( int index = 1; index <= NUM_CHARSHEET_TOOLTIP_BACKING_FRAMES; ++index ) | |||
| 18280 | { | |||
| 18281 | auto txtValueBackingFrame = characterSheetTooltipTextBackingFrames[player.playernum][index]; | |||
| 18282 | if ( txtValueBackingFrame->isDisabled() ) | |||
| 18283 | { | |||
| 18284 | continue; | |||
| 18285 | } | |||
| 18286 | ||||
| 18287 | if ( valueSizes.find(index) == valueSizes.end() ) | |||
| 18288 | { | |||
| 18289 | continue; | |||
| 18290 | } | |||
| 18291 | ||||
| 18292 | SDL_Rect valuePos = valueSizes[index].second; | |||
| 18293 | Field* entryValue = valueSizes[index].first; | |||
| 18294 | SDL_Rect entryValuePos = entryValue->getSize(); | |||
| 18295 | entryValuePos.x = entryValuePos.x + entryValuePos.w; | |||
| 18296 | entryValuePos.w = (int)longestValue; | |||
| 18297 | entryValuePos.x -= entryValuePos.w; | |||
| 18298 | entryValuePos.x -= 8; | |||
| 18299 | entryValue->setSize(entryValuePos); | |||
| 18300 | ||||
| 18301 | valuePos.w = (int)longestValue + 16; | |||
| 18302 | valuePos.x -= (valuePos.w); | |||
| 18303 | valuePos.y -= 3; | |||
| 18304 | valuePos.h += 4; | |||
| 18305 | ||||
| 18306 | txtValueBackingFrame->setSize(valuePos); | |||
| 18307 | ||||
| 18308 | imageResizeToContainer9x9(txtValueBackingFrame, SDL_Rect{ 0, 0, valuePos.w, valuePos.h }, skillsheetEffectBackgroundImages); | |||
| 18309 | } | |||
| 18310 | ||||
| 18311 | if ( !hasEntryInfoLines ) | |||
| 18312 | { | |||
| 18313 | currentHeight += padyMid * 2; | |||
| 18314 | } | |||
| 18315 | ||||
| 18316 | { | |||
| 18317 | currentHeight += padyMid; | |||
| 18318 | ||||
| 18319 | div->pos.x = padx; | |||
| 18320 | div->pos.y = currentHeight; | |||
| 18321 | div->pos.w = txtPos.w; | |||
| 18322 | div->disabled = false; | |||
| 18323 | ||||
| 18324 | currentHeight += padyMid; | |||
| 18325 | ||||
| 18326 | auto entry = characterSheetTooltipTextFields[player.playernum][15]; assert(entry)(static_cast<void> (0)); | |||
| 18327 | entry->setDisabled(false); | |||
| 18328 | char buf[512] = ""; | |||
| 18329 | ||||
| 18330 | std::string descTextFormatted = "\x1E "; | |||
| 18331 | for ( auto s : descText ) | |||
| 18332 | { | |||
| 18333 | descTextFormatted += s; | |||
| 18334 | if ( s == '\n' ) | |||
| 18335 | { | |||
| 18336 | descTextFormatted += "\x1E "; | |||
| 18337 | } | |||
| 18338 | } | |||
| 18339 | ||||
| 18340 | snprintf(buf, sizeof(buf), "%s", descTextFormatted.c_str()); | |||
| 18341 | entry->setText(buf); | |||
| 18342 | ||||
| 18343 | SDL_Rect entryPos = entry->getSize(); | |||
| 18344 | entryPos.x = padx; | |||
| 18345 | entryPos.y = currentHeight; | |||
| 18346 | entryPos.w = txtPos.w; | |||
| 18347 | entry->setSize(entryPos); | |||
| 18348 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry8 != entry->getText() ) | |||
| 18349 | { | |||
| 18350 | entry->reflowTextToFit(0); | |||
| 18351 | charsheetTooltipCache[player.playernum].textEntries[element].entry8 = entry->getText(); | |||
| 18352 | } | |||
| 18353 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 18354 | entry->setSize(entryPos); | |||
| 18355 | if ( element == SHEET_RGN && !(svFlags & SV_FLAG_HUNGER) ) | |||
| 18356 | { | |||
| 18357 | entry->setColor(hudColors.itemContextMenuHeadingText); | |||
| 18358 | } | |||
| 18359 | else if ( element == SHEET_RGN_MP && isInsectoidENRegen && !(svFlags & SV_FLAG_HUNGER) ) | |||
| 18360 | { | |||
| 18361 | entry->setColor(hudColors.itemContextMenuHeadingText); | |||
| 18362 | } | |||
| 18363 | else | |||
| 18364 | { | |||
| 18365 | entry->setColor(hudColors.characterSheetOffWhiteText); | |||
| 18366 | } | |||
| 18367 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 18368 | ||||
| 18369 | currentHeight += padyMid / 4; | |||
| 18370 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 18371 | } | |||
| 18372 | ||||
| 18373 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 18374 | if ( tooltipJustify == PANEL_JUSTIFY_RIGHT ) | |||
| 18375 | { | |||
| 18376 | tooltipPos.x = pos.x - tooltipPos.w; | |||
| 18377 | } | |||
| 18378 | else | |||
| 18379 | { | |||
| 18380 | tooltipPos.x = pos.x; | |||
| 18381 | } | |||
| 18382 | tooltipPos.y = pos.y; | |||
| 18383 | tooltipFrame->setSize(tooltipPos); | |||
| 18384 | if ( tooltipPos.y + tooltipPos.h > sheetFrame->getSize().h ) | |||
| 18385 | { | |||
| 18386 | // keep on-screen | |||
| 18387 | tooltipPos.y -= ((tooltipPos.y + tooltipPos.h) - sheetFrame->getSize().h); | |||
| 18388 | tooltipFrame->setSize(tooltipPos); | |||
| 18389 | } | |||
| 18390 | imageResizeToContainer9x9(tooltipFrame, SDL_Rect{ 0, 0, tooltipPos.w, tooltipPos.h }, | |||
| 18391 | skillsheetEffectBackgroundImages); | |||
| 18392 | } | |||
| 18393 | else if ( element == Player::CharacterSheet_t::SHEET_DUNGEON_FLOOR ) | |||
| 18394 | { | |||
| 18395 | const int maxWidth = 260; | |||
| 18396 | const int padx = 16; | |||
| 18397 | const int pady1 = 8; | |||
| 18398 | const int pady2 = 4; | |||
| 18399 | const int padxMid = 4; | |||
| 18400 | const int padyMid = 4; | |||
| 18401 | SDL_Rect tooltipPos = SDL_Rect{ 400, 0, maxWidth, 100 }; | |||
| 18402 | ||||
| 18403 | std::string descriptionText = mapDisplayNamesDescriptions[map.name].second.c_str(); | |||
| 18404 | std::string mapDetailsText = ""; | |||
| 18405 | auto mapDetails = Player::Minimap_t::mapDetails; | |||
| 18406 | for ( auto& detail : mapDetails ) | |||
| 18407 | { | |||
| 18408 | if ( mapDetailsText != "" ) | |||
| 18409 | { | |||
| 18410 | mapDetailsText += '\n'; | |||
| 18411 | } | |||
| 18412 | mapDetailsText += "\x1E "; | |||
| 18413 | mapDetailsText += detail.second; | |||
| 18414 | } | |||
| 18415 | ||||
| 18416 | if ( strcmp(descriptionText.c_str(), txt->getText()) ) | |||
| 18417 | { | |||
| 18418 | txt->setText(descriptionText.c_str()); | |||
| 18419 | } | |||
| 18420 | SDL_Rect txtPos = SDL_Rect{ padx, pady1, maxWidth - padx * 2, 80 }; | |||
| 18421 | txt->setSize(txtPos); | |||
| 18422 | if ( charsheetTooltipCache[player.playernum].textEntries[element].title != txt->getText() ) | |||
| 18423 | { | |||
| 18424 | txt->reflowTextToFit(0); | |||
| 18425 | charsheetTooltipCache[player.playernum].textEntries[element].title = txt->getText(); | |||
| 18426 | } | |||
| 18427 | Font* actualFont = Font::get(txt->getFont()); | |||
| 18428 | int txtHeight = txt->getNumTextLines() * actualFont->height(true); | |||
| 18429 | txtPos.h = txtHeight + 4; | |||
| 18430 | auto txtGet = Text::get(txt->getLongestLine().c_str(), txt->getFont(), | |||
| 18431 | txt->getTextColor(), txt->getOutlineColor()); | |||
| 18432 | txtPos.w = txtGet->getWidth(); | |||
| 18433 | txt->setSize(txtPos); | |||
| 18434 | ||||
| 18435 | tooltipPos.w = txtGet->getWidth() + padx * 2; | |||
| 18436 | ||||
| 18437 | int currentHeight = txtPos.y + txtPos.h - 4; | |||
| 18438 | ||||
| 18439 | if ( Player::Minimap_t::mapDetails.size() > 0 ) | |||
| 18440 | { | |||
| 18441 | currentHeight += padyMid; | |||
| 18442 | auto entry = tooltipFrame->findField("txt 1"); assert(entry)(static_cast<void> (0)); | |||
| 18443 | entry->setDisabled(false); | |||
| 18444 | if ( strcmp(mapDetailsText.c_str(), entry->getText()) ) | |||
| 18445 | { | |||
| 18446 | entry->setText(mapDetailsText.c_str()); | |||
| 18447 | } | |||
| 18448 | ||||
| 18449 | SDL_Rect entryPos = entry->getSize(); | |||
| 18450 | entryPos.x = padx + padxMid; | |||
| 18451 | entryPos.y = currentHeight; | |||
| 18452 | entryPos.w = tooltipPos.w - (2 * (entryPos.x)); | |||
| 18453 | entry->setSize(entryPos); | |||
| 18454 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry1 != entry->getText() ) | |||
| 18455 | { | |||
| 18456 | entry->reflowTextToFit(0); | |||
| 18457 | charsheetTooltipCache[player.playernum].textEntries[element].entry1 = entry->getText(); | |||
| 18458 | } | |||
| 18459 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + 4; | |||
| 18460 | entry->setSize(entryPos); | |||
| 18461 | entry->setColor(makeColor(255, 0, 255, 255)); | |||
| 18462 | currentHeight = std::max(entryPos.y + entryPos.h, 0); | |||
| 18463 | } | |||
| 18464 | ||||
| 18465 | if ( Player::Minimap_t::mapDetails.size() > 0 ) | |||
| 18466 | { | |||
| 18467 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 18468 | } | |||
| 18469 | else | |||
| 18470 | { | |||
| 18471 | tooltipPos.h = pady1 + txtPos.h + pady2; | |||
| 18472 | } | |||
| 18473 | if ( tooltipJustify == PANEL_JUSTIFY_RIGHT ) | |||
| 18474 | { | |||
| 18475 | tooltipPos.x = pos.x - tooltipPos.w; | |||
| 18476 | } | |||
| 18477 | else | |||
| 18478 | { | |||
| 18479 | tooltipPos.x = pos.x; | |||
| 18480 | } | |||
| 18481 | tooltipPos.y = pos.y; | |||
| 18482 | ||||
| 18483 | tooltipFrame->setSize(tooltipPos); | |||
| 18484 | imageResizeToContainer9x9(tooltipFrame, SDL_Rect{ 0, 0, tooltipPos.w, tooltipPos.h }, | |||
| 18485 | skillsheetEffectBackgroundImages); | |||
| 18486 | } | |||
| 18487 | else if ( element == Player::CharacterSheet_t::SHEET_GOLD ) | |||
| 18488 | { | |||
| 18489 | const int maxWidth = 200; | |||
| 18490 | const int padx = 16; | |||
| 18491 | const int pady1 = 8; | |||
| 18492 | const int pady2 = 8; | |||
| 18493 | const int padyMid = 4; | |||
| 18494 | const int padxMid = 4; | |||
| 18495 | SDL_Rect tooltipPos = SDL_Rect{ 400, 0, maxWidth, 100 }; | |||
| 18496 | bool usingMouse = !inputs.getVirtualMouse(player.playernum)->lastMovementFromController; | |||
| 18497 | if ( strcmp(getHoverTextString("gold_mouse").c_str(), txt->getText()) ) | |||
| 18498 | { | |||
| 18499 | txt->setText(getHoverTextString("gold_mouse").c_str()); | |||
| 18500 | } | |||
| 18501 | ||||
| 18502 | SDL_Rect txtPos = SDL_Rect{ padx, pady1, maxWidth - padx * 2, 80 }; | |||
| 18503 | txt->setSize(txtPos); | |||
| 18504 | if ( charsheetTooltipCache[player.playernum].textEntries[element].title != txt->getText() ) | |||
| 18505 | { | |||
| 18506 | txt->reflowTextToFit(0); | |||
| 18507 | charsheetTooltipCache[player.playernum].textEntries[element].title = txt->getText(); | |||
| 18508 | } | |||
| 18509 | Font* actualFont = Font::get(txt->getFont()); | |||
| 18510 | int txtHeight = txt->getNumTextLines() * actualFont->height(true); | |||
| 18511 | txtPos.h = txtHeight + padyMid; | |||
| 18512 | auto txtGet = Text::get(txt->getLongestLine().c_str(), txt->getFont(), | |||
| 18513 | txt->getTextColor(), txt->getOutlineColor()); | |||
| 18514 | txtPos.w = txtGet->getWidth(); | |||
| 18515 | txt->setSize(txtPos); | |||
| 18516 | ||||
| 18517 | tooltipPos.w = txtPos.w + padx * 2; | |||
| 18518 | tooltipPos.h = pady1 + txtPos.h + pady2; | |||
| 18519 | ||||
| 18520 | if ( tooltipJustify == PANEL_JUSTIFY_RIGHT ) | |||
| 18521 | { | |||
| 18522 | tooltipPos.x = pos.x - tooltipPos.w; | |||
| 18523 | } | |||
| 18524 | else | |||
| 18525 | { | |||
| 18526 | tooltipPos.x = pos.x; | |||
| 18527 | } | |||
| 18528 | tooltipPos.y = pos.y; | |||
| 18529 | ||||
| 18530 | tooltipFrame->setSize(tooltipPos); | |||
| 18531 | imageResizeToContainer9x9(tooltipFrame, SDL_Rect{ 0, 0, tooltipPos.w, tooltipPos.h }, | |||
| 18532 | skillsheetEffectBackgroundImages); | |||
| 18533 | } | |||
| 18534 | else if ( element == Player::CharacterSheet_t::SHEET_CHAR_RACE_SEX ) | |||
| 18535 | { | |||
| 18536 | auto tooltipTopLeft = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 18537 | tooltipTopLeft->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TL_Blue_00.png"; | |||
| 18538 | auto tooltipTop = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 18539 | tooltipTop->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_T_Blue_00.png"; | |||
| 18540 | auto tooltipTopRight = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 18541 | tooltipTopRight->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TR_Blue_00.png"; | |||
| 18542 | imageSetWidthHeight9x9(tooltipFrame, skillsheetEffectBackgroundImages); | |||
| 18543 | ||||
| 18544 | int maxWidth = 260; | |||
| 18545 | int minWidth = 0; | |||
| 18546 | ||||
| 18547 | const int padx = 16; | |||
| 18548 | const int pady1 = 8; | |||
| 18549 | const int pady2 = 4; | |||
| 18550 | const int padxMid = 4; | |||
| 18551 | const int padyMid = 8; | |||
| 18552 | SDL_Rect tooltipPos = SDL_Rect{ 400, 0, maxWidth, 100 }; | |||
| 18553 | ||||
| 18554 | Monster race = HUMAN; | |||
| 18555 | if ( stats[player.playernum]->appearance == 0 && stats[player.playernum]->playerRace != RACE_HUMAN ) | |||
| 18556 | { | |||
| 18557 | race = getMonsterFromPlayerRace(stats[player.playernum]->playerRace); | |||
| 18558 | } | |||
| 18559 | Monster modifiedRace = stats[player.playernum]->type; | |||
| 18560 | if ( arachnophobia_filter ) | |||
| 18561 | { | |||
| 18562 | if ( modifiedRace == SPIDER ) | |||
| 18563 | { | |||
| 18564 | modifiedRace = CRAB; | |||
| 18565 | } | |||
| 18566 | if ( race == SPIDER ) | |||
| 18567 | { | |||
| 18568 | race = CRAB; | |||
| 18569 | } | |||
| 18570 | } | |||
| 18571 | ||||
| 18572 | char titleBuf[64]; | |||
| 18573 | std::string titleText = getHoverTextString("race_title_normal"); | |||
| 18574 | if ( players[player.playernum]->entity ) | |||
| 18575 | { | |||
| 18576 | if ( players[player.playernum]->entity->effectShapeshift != NOTHING ) | |||
| 18577 | { | |||
| 18578 | titleText = getHoverTextString("race_title_shapeshift"); | |||
| 18579 | } | |||
| 18580 | else if ( race != modifiedRace ) | |||
| 18581 | { | |||
| 18582 | titleText = getHoverTextString("race_title_polymorph"); | |||
| 18583 | } | |||
| 18584 | } | |||
| 18585 | ||||
| 18586 | txt->setText(titleText.c_str()); | |||
| 18587 | SDL_Rect txtPos = SDL_Rect{ padx, pady1 - 2, maxWidth - padx * 2, 80 }; | |||
| 18588 | txt->setSize(txtPos); | |||
| 18589 | if ( charsheetTooltipCache[player.playernum].textEntries[element].title != txt->getText() ) | |||
| 18590 | { | |||
| 18591 | txt->reflowTextToFit(0); | |||
| 18592 | charsheetTooltipCache[player.playernum].textEntries[element].title = txt->getText(); | |||
| 18593 | } | |||
| 18594 | txt->setColor(hudColors.characterSheetHeadingText); | |||
| 18595 | Font* actualFont = Font::get(txt->getFont()); | |||
| 18596 | int txtHeight = txt->getNumTextLines() * actualFont->height(true); | |||
| 18597 | txtPos.h = txtHeight + 4; | |||
| 18598 | auto txtGet = Text::get(txt->getLongestLine().c_str(), txt->getFont(), | |||
| 18599 | txt->getTextColor(), txt->getOutlineColor()); | |||
| 18600 | txtPos.w = txtGet->getWidth(); | |||
| 18601 | txtPos.w = std::max(minWidth - padx * 2, txtPos.w); | |||
| 18602 | txt->setSize(txtPos); | |||
| 18603 | ||||
| 18604 | tooltipPos.w = (txtPos.w + padx * 2); | |||
| 18605 | ||||
| 18606 | unsigned int longestValue = 0; | |||
| 18607 | std::map<int, std::pair<Field*, SDL_Rect>> valueSizes; | |||
| 18608 | ||||
| 18609 | int currentHeight = txtPos.y + (actualFont->height(true) * 1) + 2; | |||
| 18610 | const int extraTextHeightForLowerCharacters = 4; | |||
| 18611 | currentHeight += padyMid; | |||
| 18612 | ||||
| 18613 | if ( raceTooltip ) | |||
| 18614 | { | |||
| 18615 | raceTooltip->setDisabled(false); | |||
| 18616 | MainMenu::RaceDescriptions::update_details_text(*raceTooltip, stats[player.playernum]); | |||
| 18617 | ||||
| 18618 | SDL_Rect raceTooltipPos = raceTooltip->getSize(); | |||
| 18619 | raceTooltipPos.x = txtPos.x + padxMid; | |||
| 18620 | raceTooltipPos.y = currentHeight; | |||
| 18621 | raceTooltipPos.w = 272; | |||
| 18622 | int heightOffset = 0; | |||
| 18623 | if ( auto details_text = raceTooltip->findField("details") ) | |||
| 18624 | { | |||
| 18625 | SDL_Rect pos = details_text->getSize(); | |||
| 18626 | if ( auto actualFont = Font::get(details_text->getFont()) ) | |||
| 18627 | { | |||
| 18628 | const int numlines = details_text->getNumTextLines(); | |||
| 18629 | const int pad = details_text->getPaddingPerLine(); | |||
| 18630 | const int actualHeight = actualFont->height(true); | |||
| 18631 | pos.h = 0; | |||
| 18632 | for ( int line = 0; line < numlines; ++line ) | |||
| 18633 | { | |||
| 18634 | pos.h += actualHeight + pad;// +details_text->getIndividualLinePadding(line); | |||
| 18635 | heightOffset += details_text->getIndividualLinePadding(line); | |||
| 18636 | } | |||
| 18637 | } | |||
| 18638 | raceTooltipPos.h = pos.h + pos.y + extraTextHeightForLowerCharacters; | |||
| 18639 | details_text->setSize(pos); | |||
| 18640 | } | |||
| 18641 | if ( auto details_text_right = raceTooltip->findField("details_right") ) | |||
| 18642 | { | |||
| 18643 | SDL_Rect pos = details_text_right->getSize(); | |||
| 18644 | if ( auto actualFont = Font::get(details_text_right->getFont()) ) | |||
| 18645 | { | |||
| 18646 | const int numlines = details_text_right->getNumTextLines(); | |||
| 18647 | const int pad = details_text_right->getPaddingPerLine(); | |||
| 18648 | const int actualHeight = actualFont->height(true); | |||
| 18649 | pos.h = 0; | |||
| 18650 | for ( int line = 0; line < numlines; ++line ) | |||
| 18651 | { | |||
| 18652 | pos.h += actualHeight + pad;// +details_text_right->getIndividualLinePadding(line); | |||
| 18653 | } | |||
| 18654 | } | |||
| 18655 | ||||
| 18656 | details_text_right->setSize(pos); | |||
| 18657 | } | |||
| 18658 | raceTooltip->setSize(raceTooltipPos); | |||
| 18659 | tooltipPos.w = raceTooltipPos.w + padxMid * 2; | |||
| 18660 | currentHeight = std::max(raceTooltipPos.y + raceTooltipPos.h - extraTextHeightForLowerCharacters + heightOffset, 0); | |||
| 18661 | } | |||
| 18662 | ||||
| 18663 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 18664 | if ( tooltipJustify == PANEL_JUSTIFY_RIGHT ) | |||
| 18665 | { | |||
| 18666 | tooltipPos.x = pos.x - tooltipPos.w; | |||
| 18667 | } | |||
| 18668 | else | |||
| 18669 | { | |||
| 18670 | tooltipPos.x = pos.x; | |||
| 18671 | } | |||
| 18672 | tooltipPos.y = pos.y; | |||
| 18673 | if ( tooltipPos.y + tooltipPos.h > sheetFrame->getSize().h ) | |||
| 18674 | { | |||
| 18675 | // keep on-screen | |||
| 18676 | tooltipPos.y -= ((tooltipPos.y + tooltipPos.h) - sheetFrame->getSize().h); | |||
| 18677 | tooltipFrame->setSize(tooltipPos); | |||
| 18678 | } | |||
| 18679 | tooltipFrame->setSize(tooltipPos); | |||
| 18680 | imageResizeToContainer9x9(tooltipFrame, SDL_Rect{ 0, 0, tooltipPos.w, tooltipPos.h }, | |||
| 18681 | skillsheetEffectBackgroundImages); | |||
| 18682 | } | |||
| 18683 | else if ( element == Player::CharacterSheet_t::SHEET_CHAR_CLASS ) | |||
| 18684 | { | |||
| 18685 | auto tooltipTopLeft = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 18686 | tooltipTopLeft->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TL_Blue_00.png"; | |||
| 18687 | auto tooltipTop = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 18688 | tooltipTop->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_T_Blue_00.png"; | |||
| 18689 | auto tooltipTopRight = tooltipFrame->findImage(skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 18690 | tooltipTopRight->path = "*#images/ui/CharSheet/HUD_CharSheet_Tooltip_TR_Blue_00.png"; | |||
| 18691 | imageSetWidthHeight9x9(tooltipFrame, skillsheetEffectBackgroundImages); | |||
| 18692 | ||||
| 18693 | int maxWidth = 260; | |||
| 18694 | int minWidth = 0; | |||
| 18695 | if ( getHoverTextString("stat_growth_min_tooltip_width") != defaultString ) | |||
| 18696 | { | |||
| 18697 | minWidth = std::max(0, std::stoi(getHoverTextString("stat_growth_min_tooltip_width"))); | |||
| 18698 | } | |||
| 18699 | if ( getHoverTextString("stat_growth_max_tooltip_width") != defaultString ) | |||
| 18700 | { | |||
| 18701 | maxWidth = std::max(0, std::stoi(getHoverTextString("stat_growth_max_tooltip_width"))); | |||
| 18702 | } | |||
| 18703 | ||||
| 18704 | const int padx = 16; | |||
| 18705 | const int pady1 = 8; | |||
| 18706 | const int pady2 = 4; | |||
| 18707 | const int padxMid = 4; | |||
| 18708 | const int padyMid = 8; | |||
| 18709 | SDL_Rect tooltipPos = SDL_Rect{ 400, 0, maxWidth, 100 }; | |||
| 18710 | ||||
| 18711 | Monster race = HUMAN; | |||
| 18712 | if ( stats[player.playernum]->appearance == 0 && stats[player.playernum]->playerRace != RACE_HUMAN ) | |||
| 18713 | { | |||
| 18714 | race = getMonsterFromPlayerRace(stats[player.playernum]->playerRace); | |||
| 18715 | } | |||
| 18716 | Monster modifiedRace = stats[player.playernum]->type; | |||
| 18717 | if ( arachnophobia_filter ) | |||
| 18718 | { | |||
| 18719 | if ( modifiedRace == SPIDER ) | |||
| 18720 | { | |||
| 18721 | modifiedRace = CRAB; | |||
| 18722 | } | |||
| 18723 | if ( race == SPIDER ) | |||
| 18724 | { | |||
| 18725 | race = CRAB; | |||
| 18726 | } | |||
| 18727 | } | |||
| 18728 | ||||
| 18729 | char titleBuf[64]; | |||
| 18730 | if ( player.entity && player.entity->effectShapeshift != 0 ) | |||
| 18731 | { | |||
| 18732 | txt->setText(getHoverTextString("class_title_shapeshift").c_str()); | |||
| 18733 | } | |||
| 18734 | else | |||
| 18735 | { | |||
| 18736 | txt->setText(getHoverTextString("class_title").c_str()); | |||
| 18737 | } | |||
| 18738 | SDL_Rect txtPos = SDL_Rect{ padx, pady1 - 2, maxWidth - padx * 2, 80 }; | |||
| 18739 | txt->setSize(txtPos); | |||
| 18740 | if ( charsheetTooltipCache[player.playernum].textEntries[element].title != txt->getText() ) | |||
| 18741 | { | |||
| 18742 | txt->reflowTextToFit(0); | |||
| 18743 | charsheetTooltipCache[player.playernum].textEntries[element].title = txt->getText(); | |||
| 18744 | } | |||
| 18745 | txt->setColor(hudColors.characterSheetHeadingText); | |||
| 18746 | Font* actualFont = Font::get(txt->getFont()); | |||
| 18747 | int txtHeight = txt->getNumTextLines() * actualFont->height(true); | |||
| 18748 | txtPos.h = txtHeight + 4; | |||
| 18749 | auto txtGet = Text::get(txt->getLongestLine().c_str(), txt->getFont(), | |||
| 18750 | txt->getTextColor(), txt->getOutlineColor()); | |||
| 18751 | txtPos.w = txtGet->getWidth(); | |||
| 18752 | txtPos.w = std::max(minWidth - padx * 2, txtPos.w); | |||
| 18753 | txt->setSize(txtPos); | |||
| 18754 | ||||
| 18755 | tooltipPos.w = (txtPos.w + padx * 2); | |||
| 18756 | ||||
| 18757 | std::map<int, std::pair<Field*, SDL_Rect>> valueSizes; | |||
| 18758 | ||||
| 18759 | int currentHeight = txtPos.y + (actualFont->height(true) * 1) + 2; | |||
| 18760 | const int extraTextHeightForLowerCharacters = 4; | |||
| 18761 | currentHeight += padyMid; | |||
| 18762 | ||||
| 18763 | if ( classTooltip ) | |||
| 18764 | { | |||
| 18765 | classTooltip->setDisabled(false); | |||
| 18766 | auto statGrowths = classTooltip->findFrame("stat growths"); | |||
| 18767 | if ( player.entity ) | |||
| 18768 | { | |||
| 18769 | MainMenu::ClassDescriptions::update_stat_growths(*statGrowths, client_classes[player.playernum], player.entity->effectShapeshift); | |||
| 18770 | } | |||
| 18771 | else | |||
| 18772 | { | |||
| 18773 | MainMenu::ClassDescriptions::update_stat_growths(*statGrowths, client_classes[player.playernum], 0); | |||
| 18774 | } | |||
| 18775 | ||||
| 18776 | SDL_Rect classTooltipPos = classTooltip->getSize(); | |||
| 18777 | classTooltipPos.w = statGrowths->getSize().w; | |||
| 18778 | classTooltipPos.h = statGrowths->getSize().h; | |||
| 18779 | classTooltipPos.x = tooltipPos.w / 2 - classTooltipPos.w / 2; | |||
| 18780 | classTooltipPos.y = currentHeight; | |||
| 18781 | classTooltip->setSize(classTooltipPos); | |||
| 18782 | ||||
| 18783 | currentHeight += classTooltipPos.h; | |||
| 18784 | ||||
| 18785 | std::string descText = ""; | |||
| 18786 | descText = getHoverTextString("stat_growth_info"); | |||
| 18787 | ||||
| 18788 | { | |||
| 18789 | currentHeight += padyMid; | |||
| 18790 | ||||
| 18791 | div->pos.x = padx; | |||
| 18792 | div->pos.y = currentHeight; | |||
| 18793 | div->pos.w = txtPos.w; | |||
| 18794 | div->disabled = false; | |||
| 18795 | ||||
| 18796 | currentHeight += padyMid; | |||
| 18797 | ||||
| 18798 | auto entry = characterSheetTooltipTextFields[player.playernum][1]; assert(entry)(static_cast<void> (0)); | |||
| 18799 | entry->setDisabled(false); | |||
| 18800 | char buf[512] = ""; | |||
| 18801 | ||||
| 18802 | std::string descTextFormatted = "\x1E "; | |||
| 18803 | for ( auto s : descText ) | |||
| 18804 | { | |||
| 18805 | descTextFormatted += s; | |||
| 18806 | if ( s == '\n' ) | |||
| 18807 | { | |||
| 18808 | descTextFormatted += "\x1E "; | |||
| 18809 | } | |||
| 18810 | } | |||
| 18811 | ||||
| 18812 | snprintf(buf, sizeof(buf), "%s", descTextFormatted.c_str()); | |||
| 18813 | entry->setText(buf); | |||
| 18814 | ||||
| 18815 | SDL_Rect entryPos = entry->getSize(); | |||
| 18816 | entryPos.x = padx; | |||
| 18817 | entryPos.y = currentHeight; | |||
| 18818 | entryPos.w = txtPos.w; | |||
| 18819 | entry->setSize(entryPos); | |||
| 18820 | if ( charsheetTooltipCache[player.playernum].textEntries[element].entry1 != entry->getText() ) | |||
| 18821 | { | |||
| 18822 | entry->reflowTextToFit(0); | |||
| 18823 | charsheetTooltipCache[player.playernum].textEntries[element].entry1 = entry->getText(); | |||
| 18824 | } | |||
| 18825 | entryPos.h = actualFont->height(true) * entry->getNumTextLines() + extraTextHeightForLowerCharacters; | |||
| 18826 | entry->setSize(entryPos); | |||
| 18827 | entry->setColor(hudColors.characterSheetOffWhiteText); | |||
| 18828 | currentHeight = std::max(entryPos.y + entryPos.h - extraTextHeightForLowerCharacters, 0); | |||
| 18829 | ||||
| 18830 | currentHeight += padyMid / 4; | |||
| 18831 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 18832 | } | |||
| 18833 | } | |||
| 18834 | ||||
| 18835 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 18836 | if ( tooltipJustify == PANEL_JUSTIFY_RIGHT ) | |||
| 18837 | { | |||
| 18838 | tooltipPos.x = pos.x - tooltipPos.w; | |||
| 18839 | } | |||
| 18840 | else | |||
| 18841 | { | |||
| 18842 | tooltipPos.x = pos.x; | |||
| 18843 | } | |||
| 18844 | tooltipPos.y = pos.y; | |||
| 18845 | if ( tooltipPos.y + tooltipPos.h > sheetFrame->getSize().h ) | |||
| 18846 | { | |||
| 18847 | // keep on-screen | |||
| 18848 | tooltipPos.y -= ((tooltipPos.y + tooltipPos.h) - sheetFrame->getSize().h); | |||
| 18849 | tooltipFrame->setSize(tooltipPos); | |||
| 18850 | } | |||
| 18851 | tooltipFrame->setSize(tooltipPos); | |||
| 18852 | imageResizeToContainer9x9(tooltipFrame, SDL_Rect{ 0, 0, tooltipPos.w, tooltipPos.h }, | |||
| 18853 | skillsheetEffectBackgroundImages); | |||
| 18854 | } | |||
| 18855 | else if ( element == Player::CharacterSheet_t::SHEET_TIMER ) | |||
| 18856 | { | |||
| 18857 | const int maxWidth = 240; | |||
| 18858 | const int padx = 16; | |||
| 18859 | const int pady1 = 8; | |||
| 18860 | const int pady2 = 8; | |||
| 18861 | const int padyMid = 4; | |||
| 18862 | const int padxMid = 4; | |||
| 18863 | SDL_Rect tooltipPos = SDL_Rect{ 400, 0, maxWidth, 100 }; | |||
| 18864 | bool usingMouse = !inputs.getVirtualMouse(player.playernum)->lastMovementFromController; | |||
| 18865 | ||||
| 18866 | if ( player.characterSheet.showGameTimerAlways ) | |||
| 18867 | { | |||
| 18868 | std::string tooltiptxt = getHoverTextString("game_timer_mouse") + getHoverTextString("game_timer_unpin"); | |||
| 18869 | if ( strcmp(tooltiptxt.c_str(), txt->getText()) ) | |||
| 18870 | { | |||
| 18871 | txt->setText(tooltiptxt.c_str()); | |||
| 18872 | } | |||
| 18873 | } | |||
| 18874 | else | |||
| 18875 | { | |||
| 18876 | std::string tooltiptxt = getHoverTextString("game_timer_mouse") + getHoverTextString("game_timer_pin"); | |||
| 18877 | if ( strcmp(tooltiptxt.c_str(), txt->getText()) ) | |||
| 18878 | { | |||
| 18879 | txt->setText(tooltiptxt.c_str()); | |||
| 18880 | } | |||
| 18881 | } | |||
| 18882 | ||||
| 18883 | int currentHeight = padyMid; | |||
| 18884 | ||||
| 18885 | SDL_Rect txtPos = SDL_Rect{ padx, pady1, maxWidth - padx * 2, 80 }; | |||
| 18886 | txt->setSize(txtPos); | |||
| 18887 | if ( charsheetTooltipCache[player.playernum].textEntries[element].title != txt->getText() ) | |||
| 18888 | { | |||
| 18889 | txt->reflowTextToFit(0); | |||
| 18890 | charsheetTooltipCache[player.playernum].textEntries[element].title = txt->getText(); | |||
| 18891 | } | |||
| 18892 | Font* actualFont = Font::get(txt->getFont()); | |||
| 18893 | int txtHeight = txt->getNumTextLines() * actualFont->height(true); | |||
| 18894 | txtPos.h = txtHeight + padyMid; | |||
| 18895 | auto txtGet = Text::get(txt->getLongestLine().c_str(), txt->getFont(), | |||
| 18896 | txt->getTextColor(), txt->getOutlineColor()); | |||
| 18897 | txtPos.w = txtGet->getWidth(); | |||
| 18898 | txt->setSize(txtPos); | |||
| 18899 | ||||
| 18900 | currentHeight = std::max(currentHeight, txtPos.h); | |||
| 18901 | ||||
| 18902 | tooltipPos.w = txtPos.w + padx * 2; | |||
| 18903 | tooltipPos.h = pady1 + currentHeight + pady2; | |||
| 18904 | if ( tooltipJustify == PANEL_JUSTIFY_RIGHT ) | |||
| 18905 | { | |||
| 18906 | tooltipPos.x = pos.x - tooltipPos.w; | |||
| 18907 | } | |||
| 18908 | else | |||
| 18909 | { | |||
| 18910 | tooltipPos.x = pos.x; | |||
| 18911 | } | |||
| 18912 | tooltipPos.y = pos.y; | |||
| 18913 | ||||
| 18914 | tooltipFrame->setSize(tooltipPos); | |||
| 18915 | imageResizeToContainer9x9(tooltipFrame, SDL_Rect{ 0, 0, tooltipPos.w, tooltipPos.h }, | |||
| 18916 | skillsheetEffectBackgroundImages); | |||
| 18917 | } | |||
| 18918 | } | |||
| 18919 | ||||
| 18920 | void Player::CharacterSheet_t::updateCharacterInfo() | |||
| 18921 | { | |||
| 18922 | auto characterInfoFrame = sheetFrame->findFrame("character info"); | |||
| 18923 | assert(characterInfoFrame)(static_cast<void> (0)); | |||
| 18924 | auto characterInnerFrame = characterInfoFrame->findFrame("character info inner frame"); | |||
| 18925 | assert(characterInnerFrame)(static_cast<void> (0)); | |||
| 18926 | ||||
| 18927 | bool enableTooltips = !player.GUI.isDropdownActive() && !player.GUI.dropdownMenu.bClosedThisTick; | |||
| 18928 | if ( !inputs.getVirtualMouse(player.playernum)->draw_cursor | |||
| 18929 | && inputs.hasController(player.playernum) | |||
| 18930 | && !Input::inputs[player.playernum].binary("MenuConfirm") ) | |||
| 18931 | { | |||
| 18932 | enableTooltips = false; | |||
| 18933 | } | |||
| 18934 | ||||
| 18935 | bool bCompactView = player.bUseCompactGUIHeight(); | |||
| 18936 | ||||
| 18937 | char buf[32] = ""; | |||
| 18938 | if ( auto name = characterInnerFrame->findField("character name text") ) | |||
| 18939 | { | |||
| 18940 | if ( strcmp(stats[player.playernum]->name, name->getText()) ) | |||
| 18941 | { | |||
| 18942 | name->setText(stats[player.playernum]->name); | |||
| 18943 | } | |||
| 18944 | } | |||
| 18945 | Field* className = characterInnerFrame->findField("character class text"); | |||
| 18946 | int classNameWidth = 0; | |||
| 18947 | if ( className ) | |||
| 18948 | { | |||
| 18949 | std::string classname = playerClassLangEntry(client_classes[player.playernum], player.playernum); | |||
| 18950 | if ( !classname.empty() ) | |||
| 18951 | { | |||
| 18952 | capitalizeString(classname); | |||
| 18953 | if ( strcmp(classname.c_str(), className->getText()) ) | |||
| 18954 | { | |||
| 18955 | className->setText(classname.c_str()); | |||
| 18956 | } | |||
| 18957 | } | |||
| 18958 | if ( client_classes[player.playernum] >= CLASS_CONJURER && client_classes[player.playernum] <= CLASS_BREWER ) | |||
| 18959 | { | |||
| 18960 | className->setTextColor(hudColors.characterDLC1ClassText); | |||
| 18961 | } | |||
| 18962 | else if ( client_classes[player.playernum] >= CLASS_MACHINIST && client_classes[player.playernum] <= CLASS_HUNTER ) | |||
| 18963 | { | |||
| 18964 | className->setTextColor(hudColors.characterDLC2ClassText); | |||
| 18965 | } | |||
| 18966 | else | |||
| 18967 | { | |||
| 18968 | className->setTextColor(hudColors.characterBaseClassText); | |||
| 18969 | } | |||
| 18970 | if ( auto textGet = Text::get(className->getText(), className->getFont(), | |||
| 18971 | className->getTextColor(), className->getOutlineColor()) ) | |||
| 18972 | { | |||
| 18973 | classNameWidth = textGet->getWidth(); | |||
| 18974 | } | |||
| 18975 | } | |||
| 18976 | Field* charLevel = characterInnerFrame->findField("character level text"); | |||
| 18977 | int charLevelWidth = 0; | |||
| 18978 | if ( charLevel ) | |||
| 18979 | { | |||
| 18980 | snprintf(buf, sizeof(buf), Language::get(4051), stats[player.playernum]->LVL); | |||
| 18981 | if ( strcmp(buf, charLevel->getText()) ) | |||
| 18982 | { | |||
| 18983 | charLevel->setText(buf); | |||
| 18984 | } | |||
| 18985 | if ( auto textGet = Text::get(charLevel->getText(), charLevel->getFont(), | |||
| 18986 | charLevel->getTextColor(), charLevel->getOutlineColor()) ) | |||
| 18987 | { | |||
| 18988 | charLevelWidth = textGet->getWidth(); | |||
| 18989 | } | |||
| 18990 | } | |||
| 18991 | if ( className && charLevel ) | |||
| 18992 | { | |||
| 18993 | SDL_Rect classNamePos = className->getSize(); | |||
| 18994 | SDL_Rect charLevelPos = charLevel->getSize(); | |||
| 18995 | const int padding = 24; | |||
| 18996 | const int startX = 8; | |||
| 18997 | const int fieldWidth = 190; | |||
| 18998 | const int totalWidth = charLevelWidth + padding / 2 + classNameWidth; | |||
| 18999 | charLevelPos.x = startX + fieldWidth / 2 - totalWidth / 2; | |||
| 19000 | charLevelPos.w = charLevelWidth; | |||
| 19001 | classNamePos.x = charLevelPos.x + charLevelPos.w + padding / 2 - 4; // -4 centres it nicely somehow, not sure why | |||
| 19002 | classNamePos.w = classNameWidth; | |||
| 19003 | charLevel->setSize(charLevelPos); | |||
| 19004 | className->setSize(classNamePos); | |||
| 19005 | //messagePlayer(0, "%d | %d", charLevelPos.x - startX, 198 - (classNamePos.x + classNamePos.w)); | |||
| 19006 | ||||
| 19007 | if ( selectedElement == SHEET_CHAR_CLASS && enableTooltips ) | |||
| 19008 | { | |||
| 19009 | SDL_Rect tooltipPos = characterInfoFrame->getSize(); | |||
| 19010 | tooltipPos.y -= 4; | |||
| 19011 | //tooltipPos.y += raceText->getSize().y; | |||
| 19012 | Player::PanelJustify_t tooltipJustify = PANEL_JUSTIFY_RIGHT; | |||
| 19013 | if ( (panelJustify == PANEL_JUSTIFY_LEFT && !bCompactView) || (panelJustify == PANEL_JUSTIFY_RIGHT && bCompactView) ) | |||
| 19014 | { | |||
| 19015 | tooltipJustify = PANEL_JUSTIFY_LEFT; | |||
| 19016 | tooltipPos.x += tooltipPos.w; | |||
| 19017 | } | |||
| 19018 | if ( bCompactView ) | |||
| 19019 | { | |||
| 19020 | tooltipPos.y = 0; | |||
| 19021 | tooltipPos.x += (tooltipJustify == PANEL_JUSTIFY_LEFT) ? 6 : -6; | |||
| 19022 | } | |||
| 19023 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19024 | } | |||
| 19025 | } | |||
| 19026 | if ( auto raceText = characterInnerFrame->findField("character race text") ) | |||
| 19027 | { | |||
| 19028 | Monster type = stats[player.playernum]->type; | |||
| 19029 | std::string appearance = ""; | |||
| 19030 | bool aestheticOnly = false; | |||
| 19031 | if ( player.entity ) | |||
| 19032 | { | |||
| 19033 | if ( player.entity->effectPolymorph == NOTHING && stats[player.playernum]->playerRace > RACE_HUMAN ) | |||
| 19034 | { | |||
| 19035 | if ( stats[player.playernum]->appearance != 0 ) | |||
| 19036 | { | |||
| 19037 | aestheticOnly = true; | |||
| 19038 | appearance = Language::get(4068); | |||
| 19039 | type = player.entity->getMonsterFromPlayerRace(stats[player.playernum]->playerRace); | |||
| 19040 | } | |||
| 19041 | } | |||
| 19042 | } | |||
| 19043 | std::string race = getMonsterLocalizedName(type).c_str(); | |||
| 19044 | capitalizeString(race); | |||
| 19045 | if ( type == HUMAN ) | |||
| 19046 | { | |||
| 19047 | appearance = Language::get(20 + stats[player.playernum]->appearance % NUMAPPEARANCES18); | |||
| 19048 | capitalizeString(appearance); | |||
| 19049 | } | |||
| 19050 | bool centerIconAndText = false; | |||
| 19051 | if ( appearance != "" ) | |||
| 19052 | { | |||
| 19053 | if ( aestheticOnly ) | |||
| 19054 | { | |||
| 19055 | snprintf(buf, sizeof(buf), "%s %s", appearance.c_str(), race.c_str()); // 'guised skeleton' | |||
| 19056 | } | |||
| 19057 | else | |||
| 19058 | { | |||
| 19059 | snprintf(buf, sizeof(buf), "%s %s", race.c_str(), appearance.c_str()); // 'human gloomforge' | |||
| 19060 | } | |||
| 19061 | centerIconAndText = true; | |||
| 19062 | } | |||
| 19063 | else | |||
| 19064 | { | |||
| 19065 | snprintf(buf, sizeof(buf), "%s", race.c_str()); | |||
| 19066 | } | |||
| 19067 | ||||
| 19068 | if ( strcmp(buf, raceText->getText()) ) | |||
| 19069 | { | |||
| 19070 | raceText->setText(buf); | |||
| 19071 | } | |||
| 19072 | int width = 0; | |||
| 19073 | if ( auto textGet = Text::get(raceText->getText(), raceText->getFont(), | |||
| 19074 | raceText->getTextColor(), raceText->getOutlineColor()) ) | |||
| 19075 | { | |||
| 19076 | width = textGet->getWidth(); | |||
| 19077 | } | |||
| 19078 | ||||
| 19079 | if ( auto sexImg = characterInnerFrame->findImage("character sex img") ) | |||
| 19080 | { | |||
| 19081 | int offsetx = 0; | |||
| 19082 | if ( stats[player.playernum]->sex == sex_t::MALE ) | |||
| 19083 | { | |||
| 19084 | if ( type == AUTOMATON ) | |||
| 19085 | { | |||
| 19086 | sexImg->path = "*#images/ui/CharSheet/HUD_CharSheet_Sex_AutomatonM_02.png"; | |||
| 19087 | } | |||
| 19088 | else | |||
| 19089 | { | |||
| 19090 | sexImg->path = "*#images/ui/CharSheet/HUD_CharSheet_Sex_M_02.png"; | |||
| 19091 | static ConsoleVariable<int> cvar_sexoffset("/sexoffsetx", -1); | |||
| 19092 | offsetx = *cvar_sexoffset; | |||
| 19093 | } | |||
| 19094 | } | |||
| 19095 | else if ( stats[player.playernum]->sex == sex_t::FEMALE ) | |||
| 19096 | { | |||
| 19097 | if ( type == AUTOMATON ) | |||
| 19098 | { | |||
| 19099 | sexImg->path = "*#images/ui/CharSheet/HUD_CharSheet_Sex_AutomatonF_02.png"; | |||
| 19100 | } | |||
| 19101 | else | |||
| 19102 | { | |||
| 19103 | sexImg->path = "*#images/ui/CharSheet/HUD_CharSheet_Sex_F_02.png"; | |||
| 19104 | } | |||
| 19105 | } | |||
| 19106 | if ( auto imgGet = Image::get(sexImg->path.c_str()) ) | |||
| 19107 | { | |||
| 19108 | sexImg->pos.w = (int)imgGet->getWidth(); | |||
| 19109 | sexImg->pos.h = (int)imgGet->getHeight(); | |||
| 19110 | } | |||
| 19111 | ||||
| 19112 | SDL_Rect raceTextPos = raceText->getSize(); | |||
| 19113 | raceTextPos.x = 4; | |||
| 19114 | if ( centerIconAndText ) | |||
| 19115 | { | |||
| 19116 | raceTextPos.x = 4 + (((sexImg->pos.w + 4)) / 2) + offsetx; | |||
| 19117 | } | |||
| 19118 | if ( raceTextPos.x % 2 == 1 ) | |||
| 19119 | { | |||
| 19120 | --raceTextPos.x; | |||
| 19121 | } | |||
| 19122 | raceText->setSize(raceTextPos); | |||
| 19123 | ||||
| 19124 | sexImg->pos.x = 16; | |||
| 19125 | if ( centerIconAndText ) | |||
| 19126 | { | |||
| 19127 | sexImg->pos.x = raceText->getSize().x + raceText->getSize().w / 2 - width / 2; | |||
| 19128 | sexImg->pos.x -= (sexImg->pos.w + 4) + (offsetx * 2); | |||
| 19129 | } | |||
| 19130 | if ( sexImg->pos.x % 2 == 1 ) | |||
| 19131 | { | |||
| 19132 | --sexImg->pos.x; | |||
| 19133 | } | |||
| 19134 | sexImg->pos.y = raceText->getSize().y + raceText->getSize().h / 2 - sexImg->pos.h / 2; | |||
| 19135 | } | |||
| 19136 | ||||
| 19137 | if ( selectedElement == SHEET_CHAR_RACE_SEX && enableTooltips ) | |||
| 19138 | { | |||
| 19139 | SDL_Rect tooltipPos = characterInfoFrame->getSize(); | |||
| 19140 | tooltipPos.y -= 4; | |||
| 19141 | //tooltipPos.y += raceText->getSize().y; | |||
| 19142 | Player::PanelJustify_t tooltipJustify = PANEL_JUSTIFY_RIGHT; | |||
| 19143 | if ( (panelJustify == PANEL_JUSTIFY_LEFT && !bCompactView) || (panelJustify == PANEL_JUSTIFY_RIGHT && bCompactView) ) | |||
| 19144 | { | |||
| 19145 | tooltipJustify = PANEL_JUSTIFY_LEFT; | |||
| 19146 | tooltipPos.x += tooltipPos.w; | |||
| 19147 | } | |||
| 19148 | if ( bCompactView ) | |||
| 19149 | { | |||
| 19150 | tooltipPos.y = 0; | |||
| 19151 | tooltipPos.x += (tooltipJustify == PANEL_JUSTIFY_LEFT) ? 6 : -6; | |||
| 19152 | } | |||
| 19153 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19154 | } | |||
| 19155 | } | |||
| 19156 | if ( auto floorFrame = sheetFrame->findFrame("dungeon floor frame") ) | |||
| 19157 | { | |||
| 19158 | if ( auto floorLevelText = floorFrame->findField("dungeon level text") ) | |||
| 19159 | { | |||
| 19160 | snprintf(buf, sizeof(buf), Language::get(4052), currentlevel); | |||
| 19161 | if ( strcmp(buf, floorLevelText->getText()) ) | |||
| 19162 | { | |||
| 19163 | floorLevelText->setText(buf); | |||
| 19164 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19165 | } | |||
| 19166 | } | |||
| 19167 | if ( auto floorNameText = floorFrame->findField("dungeon name text") ) | |||
| 19168 | { | |||
| 19169 | if ( mapDisplayNamesDescriptions.find(map.name) != mapDisplayNamesDescriptions.end() ) | |||
| 19170 | { | |||
| 19171 | if ( strcmp(mapDisplayNamesDescriptions[map.name].first.c_str(), floorNameText->getText()) ) | |||
| 19172 | { | |||
| 19173 | floorNameText->setText(mapDisplayNamesDescriptions[map.name].first.c_str()); | |||
| 19174 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19175 | } | |||
| 19176 | ||||
| 19177 | if ( selectedElement == SHEET_DUNGEON_FLOOR && enableTooltips ) | |||
| 19178 | { | |||
| 19179 | SDL_Rect tooltipPos = characterInfoFrame->getSize(); | |||
| 19180 | tooltipPos.y = floorFrame->getSize().y; | |||
| 19181 | Player::PanelJustify_t tooltipJustify = PANEL_JUSTIFY_RIGHT; | |||
| 19182 | if ( (panelJustify == PANEL_JUSTIFY_LEFT && !bCompactView) || (panelJustify == PANEL_JUSTIFY_RIGHT && bCompactView) ) | |||
| 19183 | { | |||
| 19184 | tooltipJustify = PANEL_JUSTIFY_LEFT; | |||
| 19185 | tooltipPos.x += tooltipPos.w; | |||
| 19186 | } | |||
| 19187 | if ( bCompactView ) | |||
| 19188 | { | |||
| 19189 | tooltipPos.y = 0; | |||
| 19190 | tooltipPos.x += (tooltipJustify == PANEL_JUSTIFY_LEFT) ? 6 : -6; | |||
| 19191 | } | |||
| 19192 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19193 | } | |||
| 19194 | } | |||
| 19195 | else | |||
| 19196 | { | |||
| 19197 | floorNameText->setText(map.name); | |||
| 19198 | } | |||
| 19199 | } | |||
| 19200 | } | |||
| 19201 | ||||
| 19202 | if ( auto gold = characterInnerFrame->findField("gold text") ) | |||
| 19203 | { | |||
| 19204 | snprintf(buf, sizeof(buf), "%d", stats[player.playernum]->GOLD); | |||
| 19205 | gold->setText(buf); | |||
| 19206 | if ( selectedElement == SHEET_GOLD ) | |||
| 19207 | { | |||
| 19208 | if ( Input::inputs[player.playernum].binary("MenuRightClick") | |||
| 19209 | && player.bControlEnabled && !gamePaused | |||
| 19210 | && !player.usingCommand() | |||
| 19211 | && player.GUI.activeModule == Player::GUI_t::MODULE_CHARACTERSHEET | |||
| 19212 | && !player.GUI.isDropdownActive() ) | |||
| 19213 | { | |||
| 19214 | player.GUI.dropdownMenu.open("drop_gold"); | |||
| 19215 | } | |||
| 19216 | else if ( (!inputs.getVirtualMouse(player.playernum)->draw_cursor | |||
| 19217 | && inputs.hasController(player.playernum) | |||
| 19218 | && Input::inputs[player.playernum].binaryToggle("MenuConfirm") | |||
| 19219 | ) | |||
| 19220 | && player.GUI.activeModule == Player::GUI_t::MODULE_CHARACTERSHEET | |||
| 19221 | && !player.GUI.isDropdownActive() | |||
| 19222 | && !player.usingCommand() | |||
| 19223 | && player.bControlEnabled && !gamePaused ) | |||
| 19224 | { | |||
| 19225 | Input::inputs[player.playernum].consumeBinaryToggle("MenuConfirm"); | |||
| 19226 | player.GUI.dropdownMenu.open("drop_gold"); | |||
| 19227 | player.GUI.dropdownMenu.dropDownToggleClick = true; | |||
| 19228 | SDL_Rect dropdownPos = characterInfoFrame->getSize(); | |||
| 19229 | dropdownPos.y += gold->getSize().y + gold->getSize().h / 2; | |||
| 19230 | if ( auto interactMenuTop = player.GUI.dropdownMenu.dropdownFrame->findImage("interact top background") ) | |||
| 19231 | { | |||
| 19232 | // 10px is slot half height, move by 1.5 slots, minus the top interact text height | |||
| 19233 | dropdownPos.y -= (interactMenuTop->pos.h + (3 * 10) + 4); | |||
| 19234 | } | |||
| 19235 | if ( !player.GUI.dropdownMenu.getDropDownAlignRight("drop_gold") ) | |||
| 19236 | { | |||
| 19237 | player.GUI.dropdownMenu.dropDownX = dropdownPos.x; | |||
| 19238 | } | |||
| 19239 | else | |||
| 19240 | { | |||
| 19241 | player.GUI.dropdownMenu.dropDownX = dropdownPos.x + dropdownPos.w; | |||
| 19242 | } | |||
| 19243 | player.GUI.dropdownMenu.dropDownX += player.camera_virtualx1(); | |||
| 19244 | player.GUI.dropdownMenu.dropDownY = dropdownPos.y + player.camera_virtualy1(); | |||
| 19245 | } | |||
| 19246 | if ( enableTooltips && !inputs.getVirtualMouse(player.playernum)->lastMovementFromController ) | |||
| 19247 | { | |||
| 19248 | SDL_Rect tooltipPos = characterInfoFrame->getSize(); | |||
| 19249 | tooltipPos.y += gold->getSize().y; | |||
| 19250 | tooltipPos.y -= 6; | |||
| 19251 | Player::PanelJustify_t tooltipJustify = PANEL_JUSTIFY_RIGHT; | |||
| 19252 | if ( (panelJustify == PANEL_JUSTIFY_LEFT && !bCompactView) || (panelJustify == PANEL_JUSTIFY_RIGHT && bCompactView) ) | |||
| 19253 | { | |||
| 19254 | tooltipJustify = PANEL_JUSTIFY_LEFT; | |||
| 19255 | tooltipPos.x += tooltipPos.w; | |||
| 19256 | } | |||
| 19257 | if ( bCompactView ) | |||
| 19258 | { | |||
| 19259 | tooltipPos.x += (tooltipJustify == PANEL_JUSTIFY_LEFT) ? 6 : -6; | |||
| 19260 | } | |||
| 19261 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19262 | } | |||
| 19263 | } | |||
| 19264 | } | |||
| 19265 | } | |||
| 19266 | ||||
| 19267 | void Player::CharacterSheet_t::updateStats() | |||
| 19268 | { | |||
| 19269 | auto characterInfoFrame = sheetFrame->findFrame("character info"); | |||
| 19270 | assert(characterInfoFrame)(static_cast<void> (0)); | |||
| 19271 | auto characterInnerFrame = characterInfoFrame->findFrame("character info inner frame"); | |||
| 19272 | assert(characterInnerFrame)(static_cast<void> (0)); | |||
| 19273 | auto statsFrame = sheetFrame->findFrame("stats"); | |||
| 19274 | assert(statsFrame)(static_cast<void> (0)); | |||
| 19275 | ||||
| 19276 | auto statsPos = statsFrame->getSize(); | |||
| 19277 | //statsPos.x = sheetFrame->getSize().w - statsPos.w; | |||
| 19278 | statsFrame->setSize(statsPos); | |||
| 19279 | ||||
| 19280 | auto statsInnerFrame = statsFrame->findFrame("stats inner frame"); | |||
| 19281 | assert(statsInnerFrame)(static_cast<void> (0)); | |||
| 19282 | ||||
| 19283 | const int rightAlignPosX = 0; | |||
| 19284 | const int leftAlignPosX = 10; | |||
| 19285 | auto statsInnerPos = statsInnerFrame->getSize(); | |||
| 19286 | statsInnerPos.x = rightAlignPosX; | |||
| 19287 | /*if ( keystatus[SDLK_I] && enableDebugKeys ) | |||
| 19288 | { | |||
| 19289 | statsInnerPos.x = leftAlignPosX; | |||
| 19290 | }*/ | |||
| 19291 | statsInnerFrame->setSize(statsInnerPos); | |||
| 19292 | Button* strButton = statsInnerFrame->findButton("str button"); | |||
| 19293 | Button* dexButton = statsInnerFrame->findButton("dex button"); | |||
| 19294 | Button* conButton = statsInnerFrame->findButton("con button"); | |||
| 19295 | Button* intButton = statsInnerFrame->findButton("int button"); | |||
| 19296 | Button* perButton = statsInnerFrame->findButton("per button"); | |||
| 19297 | Button* chrButton = statsInnerFrame->findButton("chr button"); | |||
| 19298 | ||||
| 19299 | bool bCompactView = player.bUseCompactGUIHeight(); | |||
| 19300 | ||||
| 19301 | bool enableTooltips = !player.GUI.isDropdownActive() && !player.GUI.dropdownMenu.bClosedThisTick; | |||
| 19302 | if ( !inputs.getVirtualMouse(player.playernum)->draw_cursor | |||
| 19303 | && inputs.hasController(player.playernum) | |||
| 19304 | && !Input::inputs[player.playernum].binary("MenuConfirm") ) | |||
| 19305 | { | |||
| 19306 | enableTooltips = false; | |||
| 19307 | } | |||
| 19308 | char buf[32] = ""; | |||
| 19309 | if ( auto field = statsInnerFrame->findField("str text stat") ) | |||
| 19310 | { | |||
| 19311 | snprintf(buf, sizeof(buf), "%d", stats[player.playernum]->STR); | |||
| 19312 | if ( strcmp(buf, field->getText()) ) | |||
| 19313 | { | |||
| 19314 | field->setText(buf); | |||
| 19315 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19316 | } | |||
| 19317 | field->setColor(hudColors.characterSheetNeutral); | |||
| 19318 | ||||
| 19319 | Sint32 modifiedStat = statGetSTR(stats[player.playernum], players[player.playernum]->entity); | |||
| 19320 | if ( auto modifiedField = statsInnerFrame->findField("str text modified") ) | |||
| 19321 | { | |||
| 19322 | modifiedField->setColor(hudColors.characterSheetNeutral); | |||
| 19323 | modifiedField->setDisabled(true); | |||
| 19324 | snprintf(buf, sizeof(buf), "%d", modifiedStat); | |||
| 19325 | if ( strcmp(buf, modifiedField->getText()) ) | |||
| 19326 | { | |||
| 19327 | modifiedField->setText(buf); | |||
| 19328 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19329 | } | |||
| 19330 | if ( modifiedStat > stats[player.playernum]->STR ) | |||
| 19331 | { | |||
| 19332 | modifiedField->setColor(hudColors.characterSheetGreen); | |||
| 19333 | modifiedField->setDisabled(false); | |||
| 19334 | } | |||
| 19335 | else if ( modifiedStat < stats[player.playernum]->STR ) | |||
| 19336 | { | |||
| 19337 | modifiedField->setColor(hudColors.characterSheetRed); | |||
| 19338 | modifiedField->setDisabled(false); | |||
| 19339 | } | |||
| 19340 | } | |||
| 19341 | if ( selectedElement == SHEET_STR && enableTooltips ) | |||
| 19342 | { | |||
| 19343 | SDL_Rect tooltipPos = statsFrame->getSize(); | |||
| 19344 | tooltipPos.y += statsInnerFrame->getSize().y; | |||
| 19345 | Player::PanelJustify_t tooltipJustify = panelJustify; | |||
| 19346 | if ( panelJustify == PANEL_JUSTIFY_LEFT ) | |||
| 19347 | { | |||
| 19348 | tooltipPos.x += tooltipPos.w; | |||
| 19349 | } | |||
| 19350 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19351 | } | |||
| 19352 | } | |||
| 19353 | if ( auto field = statsInnerFrame->findField("dex text stat") ) | |||
| 19354 | { | |||
| 19355 | snprintf(buf, sizeof(buf), "%d", stats[player.playernum]->DEX); | |||
| 19356 | if ( strcmp(buf, field->getText()) ) | |||
| 19357 | { | |||
| 19358 | field->setText(buf); | |||
| 19359 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19360 | } | |||
| 19361 | field->setColor(hudColors.characterSheetNeutral); | |||
| 19362 | ||||
| 19363 | Sint32 modifiedStat = statGetDEX(stats[player.playernum], players[player.playernum]->entity); | |||
| 19364 | if ( auto modifiedField = statsInnerFrame->findField("dex text modified") ) | |||
| 19365 | { | |||
| 19366 | modifiedField->setColor(hudColors.characterSheetNeutral); | |||
| 19367 | modifiedField->setDisabled(true); | |||
| 19368 | snprintf(buf, sizeof(buf), "%d", modifiedStat); | |||
| 19369 | if ( strcmp(buf, modifiedField->getText()) ) | |||
| 19370 | { | |||
| 19371 | modifiedField->setText(buf); | |||
| 19372 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19373 | } | |||
| 19374 | if ( modifiedStat > stats[player.playernum]->DEX ) | |||
| 19375 | { | |||
| 19376 | modifiedField->setColor(hudColors.characterSheetGreen); | |||
| 19377 | modifiedField->setDisabled(false); | |||
| 19378 | } | |||
| 19379 | else if ( modifiedStat < stats[player.playernum]->DEX ) | |||
| 19380 | { | |||
| 19381 | modifiedField->setColor(hudColors.characterSheetRed); | |||
| 19382 | modifiedField->setDisabled(false); | |||
| 19383 | } | |||
| 19384 | } | |||
| 19385 | if ( selectedElement == SHEET_DEX && enableTooltips ) | |||
| 19386 | { | |||
| 19387 | SDL_Rect tooltipPos = statsFrame->getSize(); | |||
| 19388 | tooltipPos.y += statsInnerFrame->getSize().y; | |||
| 19389 | Player::PanelJustify_t tooltipJustify = panelJustify; | |||
| 19390 | if ( panelJustify == PANEL_JUSTIFY_LEFT ) | |||
| 19391 | { | |||
| 19392 | tooltipPos.x += tooltipPos.w; | |||
| 19393 | } | |||
| 19394 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19395 | } | |||
| 19396 | } | |||
| 19397 | if ( auto field = statsInnerFrame->findField("con text stat") ) | |||
| 19398 | { | |||
| 19399 | snprintf(buf, sizeof(buf), "%d", stats[player.playernum]->CON); | |||
| 19400 | if ( strcmp(buf, field->getText()) ) | |||
| 19401 | { | |||
| 19402 | field->setText(buf); | |||
| 19403 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19404 | } | |||
| 19405 | field->setColor(hudColors.characterSheetNeutral); | |||
| 19406 | ||||
| 19407 | Sint32 modifiedStat = statGetCON(stats[player.playernum], players[player.playernum]->entity); | |||
| 19408 | if ( auto modifiedField = statsInnerFrame->findField("con text modified") ) | |||
| 19409 | { | |||
| 19410 | modifiedField->setColor(hudColors.characterSheetNeutral); | |||
| 19411 | modifiedField->setDisabled(true); | |||
| 19412 | snprintf(buf, sizeof(buf), "%d", modifiedStat); | |||
| 19413 | if ( strcmp(buf, modifiedField->getText()) ) | |||
| 19414 | { | |||
| 19415 | modifiedField->setText(buf); | |||
| 19416 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19417 | } | |||
| 19418 | if ( modifiedStat > stats[player.playernum]->CON ) | |||
| 19419 | { | |||
| 19420 | modifiedField->setColor(hudColors.characterSheetGreen); | |||
| 19421 | modifiedField->setDisabled(false); | |||
| 19422 | } | |||
| 19423 | else if ( modifiedStat < stats[player.playernum]->CON ) | |||
| 19424 | { | |||
| 19425 | modifiedField->setColor(hudColors.characterSheetRed); | |||
| 19426 | modifiedField->setDisabled(false); | |||
| 19427 | } | |||
| 19428 | } | |||
| 19429 | if ( selectedElement == SHEET_CON && enableTooltips ) | |||
| 19430 | { | |||
| 19431 | SDL_Rect tooltipPos = statsFrame->getSize(); | |||
| 19432 | tooltipPos.y += statsInnerFrame->getSize().y; | |||
| 19433 | Player::PanelJustify_t tooltipJustify = panelJustify; | |||
| 19434 | if ( panelJustify == PANEL_JUSTIFY_LEFT ) | |||
| 19435 | { | |||
| 19436 | tooltipPos.x += tooltipPos.w; | |||
| 19437 | } | |||
| 19438 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19439 | } | |||
| 19440 | } | |||
| 19441 | if ( auto field = statsInnerFrame->findField("int text stat") ) | |||
| 19442 | { | |||
| 19443 | snprintf(buf, sizeof(buf), "%d", stats[player.playernum]->INT); | |||
| 19444 | if ( strcmp(buf, field->getText()) ) | |||
| 19445 | { | |||
| 19446 | field->setText(buf); | |||
| 19447 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19448 | } | |||
| 19449 | field->setColor(hudColors.characterSheetNeutral); | |||
| 19450 | ||||
| 19451 | Sint32 modifiedStat = statGetINT(stats[player.playernum], players[player.playernum]->entity); | |||
| 19452 | if ( auto modifiedField = statsInnerFrame->findField("int text modified") ) | |||
| 19453 | { | |||
| 19454 | modifiedField->setColor(hudColors.characterSheetNeutral); | |||
| 19455 | modifiedField->setDisabled(true); | |||
| 19456 | snprintf(buf, sizeof(buf), "%d", modifiedStat); | |||
| 19457 | if ( strcmp(buf, modifiedField->getText()) ) | |||
| 19458 | { | |||
| 19459 | modifiedField->setText(buf); | |||
| 19460 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19461 | } | |||
| 19462 | if ( modifiedStat > stats[player.playernum]->INT ) | |||
| 19463 | { | |||
| 19464 | modifiedField->setColor(hudColors.characterSheetGreen); | |||
| 19465 | modifiedField->setDisabled(false); | |||
| 19466 | } | |||
| 19467 | else if ( modifiedStat < stats[player.playernum]->INT ) | |||
| 19468 | { | |||
| 19469 | modifiedField->setColor(hudColors.characterSheetRed); | |||
| 19470 | modifiedField->setDisabled(false); | |||
| 19471 | } | |||
| 19472 | } | |||
| 19473 | if ( selectedElement == SHEET_INT && enableTooltips ) | |||
| 19474 | { | |||
| 19475 | SDL_Rect tooltipPos = statsFrame->getSize(); | |||
| 19476 | tooltipPos.y += statsInnerFrame->getSize().y; | |||
| 19477 | Player::PanelJustify_t tooltipJustify = panelJustify; | |||
| 19478 | if ( panelJustify == PANEL_JUSTIFY_LEFT ) | |||
| 19479 | { | |||
| 19480 | tooltipPos.x += tooltipPos.w; | |||
| 19481 | } | |||
| 19482 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19483 | } | |||
| 19484 | } | |||
| 19485 | if ( auto field = statsInnerFrame->findField("per text stat") ) | |||
| 19486 | { | |||
| 19487 | snprintf(buf, sizeof(buf), "%d", stats[player.playernum]->PER); | |||
| 19488 | if ( strcmp(buf, field->getText()) ) | |||
| 19489 | { | |||
| 19490 | field->setText(buf); | |||
| 19491 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19492 | } | |||
| 19493 | field->setColor(hudColors.characterSheetNeutral); | |||
| 19494 | ||||
| 19495 | Sint32 modifiedStat = statGetPER(stats[player.playernum], players[player.playernum]->entity); | |||
| 19496 | if ( auto modifiedField = statsInnerFrame->findField("per text modified") ) | |||
| 19497 | { | |||
| 19498 | modifiedField->setColor(hudColors.characterSheetNeutral); | |||
| 19499 | modifiedField->setDisabled(true); | |||
| 19500 | snprintf(buf, sizeof(buf), "%d", modifiedStat); | |||
| 19501 | if ( strcmp(buf, modifiedField->getText()) ) | |||
| 19502 | { | |||
| 19503 | modifiedField->setText(buf); | |||
| 19504 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19505 | } | |||
| 19506 | if ( modifiedStat > stats[player.playernum]->PER ) | |||
| 19507 | { | |||
| 19508 | modifiedField->setColor(hudColors.characterSheetGreen); | |||
| 19509 | modifiedField->setDisabled(false); | |||
| 19510 | } | |||
| 19511 | else if ( modifiedStat < stats[player.playernum]->PER ) | |||
| 19512 | { | |||
| 19513 | modifiedField->setColor(hudColors.characterSheetRed); | |||
| 19514 | modifiedField->setDisabled(false); | |||
| 19515 | } | |||
| 19516 | } | |||
| 19517 | if ( selectedElement == SHEET_PER && enableTooltips ) | |||
| 19518 | { | |||
| 19519 | SDL_Rect tooltipPos = statsFrame->getSize(); | |||
| 19520 | tooltipPos.y += statsInnerFrame->getSize().y; | |||
| 19521 | Player::PanelJustify_t tooltipJustify = panelJustify; | |||
| 19522 | if ( panelJustify == PANEL_JUSTIFY_LEFT ) | |||
| 19523 | { | |||
| 19524 | tooltipPos.x += tooltipPos.w; | |||
| 19525 | } | |||
| 19526 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19527 | } | |||
| 19528 | } | |||
| 19529 | if ( auto field = statsInnerFrame->findField("chr text stat") ) | |||
| 19530 | { | |||
| 19531 | snprintf(buf, sizeof(buf), "%d", stats[player.playernum]->CHR); | |||
| 19532 | if ( strcmp(buf, field->getText()) ) | |||
| 19533 | { | |||
| 19534 | field->setText(buf); | |||
| 19535 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19536 | } | |||
| 19537 | field->setColor(hudColors.characterSheetNeutral); | |||
| 19538 | ||||
| 19539 | Sint32 modifiedStat = statGetCHR(stats[player.playernum], players[player.playernum]->entity); | |||
| 19540 | if ( auto modifiedField = statsInnerFrame->findField("chr text modified") ) | |||
| 19541 | { | |||
| 19542 | modifiedField->setColor(hudColors.characterSheetNeutral); | |||
| 19543 | modifiedField->setDisabled(true); | |||
| 19544 | snprintf(buf, sizeof(buf), "%d", modifiedStat); | |||
| 19545 | if ( strcmp(buf, modifiedField->getText()) ) | |||
| 19546 | { | |||
| 19547 | modifiedField->setText(buf); | |||
| 19548 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19549 | } | |||
| 19550 | if ( modifiedStat > stats[player.playernum]->CHR ) | |||
| 19551 | { | |||
| 19552 | modifiedField->setColor(hudColors.characterSheetGreen); | |||
| 19553 | modifiedField->setDisabled(false); | |||
| 19554 | } | |||
| 19555 | else if ( modifiedStat < stats[player.playernum]->CHR ) | |||
| 19556 | { | |||
| 19557 | modifiedField->setColor(hudColors.characterSheetRed); | |||
| 19558 | modifiedField->setDisabled(false); | |||
| 19559 | } | |||
| 19560 | } | |||
| 19561 | if ( selectedElement == SHEET_CHR && enableTooltips ) | |||
| 19562 | { | |||
| 19563 | SDL_Rect tooltipPos = statsFrame->getSize(); | |||
| 19564 | tooltipPos.y += statsInnerFrame->getSize().y; | |||
| 19565 | Player::PanelJustify_t tooltipJustify = panelJustify; | |||
| 19566 | if ( panelJustify == PANEL_JUSTIFY_LEFT ) | |||
| 19567 | { | |||
| 19568 | tooltipPos.x += tooltipPos.w; | |||
| 19569 | } | |||
| 19570 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19571 | } | |||
| 19572 | } | |||
| 19573 | } | |||
| 19574 | ||||
| 19575 | void Player::CharacterSheet_t::updateAttributes() | |||
| 19576 | { | |||
| 19577 | auto attributesFrame = sheetFrame->findFrame("attributes"); | |||
| 19578 | assert(attributesFrame)(static_cast<void> (0)); | |||
| 19579 | ||||
| 19580 | auto attributesPos = attributesFrame->getSize(); | |||
| 19581 | //attributesPos.x = sheetFrame->getSize().w - attributesPos.w; | |||
| 19582 | attributesFrame->setSize(attributesPos); | |||
| 19583 | ||||
| 19584 | auto attributesInnerFrame = attributesFrame->findFrame("attributes inner frame"); | |||
| 19585 | assert(attributesInnerFrame)(static_cast<void> (0)); | |||
| 19586 | ||||
| 19587 | const int rightAlignPosX = 0; | |||
| 19588 | const int leftAlignPosX = 10; | |||
| 19589 | auto attributesInnerPos = attributesInnerFrame->getSize(); | |||
| 19590 | attributesInnerPos.x = rightAlignPosX; | |||
| 19591 | /*if ( keystatus[SDLK_I] ) | |||
| 19592 | { | |||
| 19593 | attributesInnerPos.x = leftAlignPosX; | |||
| 19594 | }*/ | |||
| 19595 | attributesInnerFrame->setSize(attributesInnerPos); | |||
| 19596 | ||||
| 19597 | bool bCompactView = player.bUseCompactGUIHeight(); | |||
| 19598 | ||||
| 19599 | bool enableTooltips = !player.GUI.isDropdownActive() && !player.GUI.dropdownMenu.bClosedThisTick; | |||
| 19600 | if ( !inputs.getVirtualMouse(player.playernum)->draw_cursor | |||
| 19601 | && inputs.hasController(player.playernum) | |||
| 19602 | && !Input::inputs[player.playernum].binary("MenuConfirm") ) | |||
| 19603 | { | |||
| 19604 | enableTooltips = false; | |||
| 19605 | } | |||
| 19606 | ||||
| 19607 | char buf[32] = ""; | |||
| 19608 | ||||
| 19609 | if ( auto field = attributesInnerFrame->findField("atk text stat") ) | |||
| 19610 | { | |||
| 19611 | AttackHoverText_t atkHoverText; | |||
| 19612 | Sint32 displayedATK = displayAttackPower(player.playernum, atkHoverText); | |||
| 19613 | if ( atkHoverText.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_MAGICSTAFF | |||
| 19614 | || atkHoverText.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_TOOL | |||
| 19615 | || atkHoverText.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_TOOL_TRAP | |||
| 19616 | || atkHoverText.hoverType == AttackHoverText_t::ATK_HOVER_TYPE_DEFAULT ) | |||
| 19617 | { | |||
| 19618 | snprintf(buf, sizeof(buf), "-"); | |||
| 19619 | } | |||
| 19620 | else | |||
| 19621 | { | |||
| 19622 | snprintf(buf, sizeof(buf), "%d", displayedATK); | |||
| 19623 | } | |||
| 19624 | if ( strcmp(buf, field->getText()) ) | |||
| 19625 | { | |||
| 19626 | field->setText(buf); | |||
| 19627 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19628 | } | |||
| 19629 | field->setColor(hudColors.characterSheetNeutral); | |||
| 19630 | ||||
| 19631 | if ( selectedElement == SHEET_ATK && enableTooltips ) | |||
| 19632 | { | |||
| 19633 | SDL_Rect tooltipPos = attributesFrame->getSize(); | |||
| 19634 | tooltipPos.y += attributesInnerFrame->getSize().y; | |||
| 19635 | Player::PanelJustify_t tooltipJustify = panelJustify; | |||
| 19636 | if ( panelJustify == PANEL_JUSTIFY_LEFT ) | |||
| 19637 | { | |||
| 19638 | tooltipPos.x += tooltipPos.w; | |||
| 19639 | } | |||
| 19640 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19641 | } | |||
| 19642 | } | |||
| 19643 | ||||
| 19644 | if ( auto field = attributesInnerFrame->findField("ac text stat") ) | |||
| 19645 | { | |||
| 19646 | snprintf(buf, sizeof(buf), "%d", AC(stats[player.playernum])); | |||
| 19647 | if ( strcmp(buf, field->getText()) ) | |||
| 19648 | { | |||
| 19649 | field->setText(buf); | |||
| 19650 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19651 | } | |||
| 19652 | field->setColor(hudColors.characterSheetNeutral); | |||
| 19653 | ||||
| 19654 | if ( selectedElement == SHEET_AC && enableTooltips ) | |||
| 19655 | { | |||
| 19656 | SDL_Rect tooltipPos = attributesFrame->getSize(); | |||
| 19657 | tooltipPos.y += attributesInnerFrame->getSize().y; | |||
| 19658 | Player::PanelJustify_t tooltipJustify = panelJustify; | |||
| 19659 | if ( panelJustify == PANEL_JUSTIFY_LEFT ) | |||
| 19660 | { | |||
| 19661 | tooltipPos.x += tooltipPos.w; | |||
| 19662 | } | |||
| 19663 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19664 | } | |||
| 19665 | } | |||
| 19666 | ||||
| 19667 | if ( auto field = attributesInnerFrame->findField("pwr text stat") ) | |||
| 19668 | { | |||
| 19669 | real_t spellPower = (getBonusFromCasterOfSpellElement(player.entity, stats[player.playernum], nullptr, SPELL_NONE) * 100.0) + 100.0; | |||
| 19670 | snprintf(buf, sizeof(buf), "%.f%%", spellPower); | |||
| 19671 | if ( strcmp(buf, field->getText()) ) | |||
| 19672 | { | |||
| 19673 | field->setText(buf); | |||
| 19674 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19675 | } | |||
| 19676 | field->setColor(hudColors.characterSheetNeutral); | |||
| 19677 | ||||
| 19678 | if ( selectedElement == SHEET_POW && enableTooltips ) | |||
| 19679 | { | |||
| 19680 | SDL_Rect tooltipPos = attributesFrame->getSize(); | |||
| 19681 | tooltipPos.y += attributesInnerFrame->getSize().y; | |||
| 19682 | Player::PanelJustify_t tooltipJustify = panelJustify; | |||
| 19683 | if ( panelJustify == PANEL_JUSTIFY_LEFT ) | |||
| 19684 | { | |||
| 19685 | tooltipPos.x += tooltipPos.w; | |||
| 19686 | } | |||
| 19687 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19688 | } | |||
| 19689 | } | |||
| 19690 | ||||
| 19691 | if ( auto field = attributesInnerFrame->findField("res text stat") ) | |||
| 19692 | { | |||
| 19693 | real_t resistance = 100.0 * Entity::getDamageTableMultiplier(player.entity, *stats[player.playernum], DAMAGE_TABLE_MAGIC); | |||
| 19694 | resistance /= (Entity::getMagicResistance(stats[player.playernum]) + 1); | |||
| 19695 | resistance = -(resistance - 100.0); | |||
| 19696 | snprintf(buf, sizeof(buf), "%d%%", (int)resistance); | |||
| 19697 | if ( strcmp(buf, field->getText()) ) | |||
| 19698 | { | |||
| 19699 | field->setText(buf); | |||
| 19700 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19701 | } | |||
| 19702 | field->setColor(hudColors.characterSheetNeutral); | |||
| 19703 | if ( resistance > 0.01 ) | |||
| 19704 | { | |||
| 19705 | field->setColor(hudColors.characterSheetGreen); | |||
| 19706 | } | |||
| 19707 | else if ( resistance < -0.01 ) | |||
| 19708 | { | |||
| 19709 | field->setColor(hudColors.characterSheetRed); | |||
| 19710 | } | |||
| 19711 | ||||
| 19712 | if ( selectedElement == SHEET_RES && enableTooltips ) | |||
| 19713 | { | |||
| 19714 | SDL_Rect tooltipPos = attributesFrame->getSize(); | |||
| 19715 | tooltipPos.y += attributesInnerFrame->getSize().y; | |||
| 19716 | Player::PanelJustify_t tooltipJustify = panelJustify; | |||
| 19717 | if ( panelJustify == PANEL_JUSTIFY_LEFT ) | |||
| 19718 | { | |||
| 19719 | tooltipPos.x += tooltipPos.w; | |||
| 19720 | } | |||
| 19721 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19722 | } | |||
| 19723 | } | |||
| 19724 | ||||
| 19725 | if ( auto field = attributesInnerFrame->findField("regen text hp") ) | |||
| 19726 | { | |||
| 19727 | field->setColor(hudColors.characterSheetNeutral); | |||
| 19728 | Uint32 color = hudColors.characterSheetNeutral; | |||
| 19729 | getDisplayedHPRegen(players[player.playernum]->entity, *stats[player.playernum], &color, buf); | |||
| 19730 | if ( strcmp(buf, field->getText()) ) | |||
| 19731 | { | |||
| 19732 | field->setText(buf); | |||
| 19733 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19734 | } | |||
| 19735 | field->setColor(color); | |||
| 19736 | ||||
| 19737 | if ( selectedElement == SHEET_RGN && enableTooltips ) | |||
| 19738 | { | |||
| 19739 | SDL_Rect tooltipPos = attributesFrame->getSize(); | |||
| 19740 | tooltipPos.y += attributesInnerFrame->getSize().y; | |||
| 19741 | Player::PanelJustify_t tooltipJustify = panelJustify; | |||
| 19742 | if ( panelJustify == PANEL_JUSTIFY_LEFT ) | |||
| 19743 | { | |||
| 19744 | tooltipPos.x += tooltipPos.w; | |||
| 19745 | } | |||
| 19746 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19747 | } | |||
| 19748 | } | |||
| 19749 | ||||
| 19750 | if ( auto field = attributesInnerFrame->findField("regen text mp") ) | |||
| 19751 | { | |||
| 19752 | field->setColor(hudColors.characterSheetNeutral); | |||
| 19753 | Uint32 color = hudColors.characterSheetNeutral; | |||
| 19754 | getDisplayedMPRegen(players[player.playernum]->entity, *stats[player.playernum], &color, buf); | |||
| 19755 | if ( strcmp(buf, field->getText()) ) | |||
| 19756 | { | |||
| 19757 | field->setText(buf); | |||
| 19758 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19759 | } | |||
| 19760 | field->setColor(color); | |||
| 19761 | ||||
| 19762 | if ( selectedElement == SHEET_RGN_MP && enableTooltips ) | |||
| 19763 | { | |||
| 19764 | SDL_Rect tooltipPos = attributesFrame->getSize(); | |||
| 19765 | tooltipPos.y += attributesInnerFrame->getSize().y; | |||
| 19766 | Player::PanelJustify_t tooltipJustify = panelJustify; | |||
| 19767 | if ( panelJustify == PANEL_JUSTIFY_LEFT ) | |||
| 19768 | { | |||
| 19769 | tooltipPos.x += tooltipPos.w; | |||
| 19770 | } | |||
| 19771 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19772 | } | |||
| 19773 | } | |||
| 19774 | ||||
| 19775 | ||||
| 19776 | if ( auto field = attributesInnerFrame->findField("weight text stat") ) | |||
| 19777 | { | |||
| 19778 | Sint32 weight = 0; | |||
| 19779 | for ( node_t* node = stats[player.playernum]->inventory.first; node != NULL__null; node = node->next ) | |||
| 19780 | { | |||
| 19781 | Item* item = (Item*)node->element; | |||
| 19782 | if ( item ) | |||
| 19783 | { | |||
| 19784 | weight += item->getWeight(); | |||
| 19785 | } | |||
| 19786 | } | |||
| 19787 | weight += stats[player.playernum]->getGoldWeight(); | |||
| 19788 | snprintf(buf, sizeof(buf), "%d", weight); | |||
| 19789 | if ( strcmp(buf, field->getText()) ) | |||
| 19790 | { | |||
| 19791 | field->setText(buf); | |||
| 19792 | charsheetTooltipCache[player.playernum].manualUpdate = true; | |||
| 19793 | } | |||
| 19794 | field->setColor(hudColors.characterSheetNeutral); | |||
| 19795 | ||||
| 19796 | if ( selectedElement == SHEET_WGT && enableTooltips ) | |||
| 19797 | { | |||
| 19798 | SDL_Rect tooltipPos = attributesFrame->getSize(); | |||
| 19799 | tooltipPos.y += attributesInnerFrame->getSize().y; | |||
| 19800 | Player::PanelJustify_t tooltipJustify = panelJustify; | |||
| 19801 | if ( panelJustify == PANEL_JUSTIFY_LEFT ) | |||
| 19802 | { | |||
| 19803 | tooltipPos.x += tooltipPos.w; | |||
| 19804 | } | |||
| 19805 | updateCharacterSheetTooltip(selectedElement, tooltipPos, tooltipJustify); | |||
| 19806 | } | |||
| 19807 | } | |||
| 19808 | } | |||
| 19809 | ||||
| 19810 | void Player::Hotbar_t::processHotbar() | |||
| 19811 | { | |||
| 19812 | #ifndef NINTENDO | |||
| 19813 | if ( inputs.hasController(player.playernum) ) | |||
| 19814 | { | |||
| 19815 | useHotbarFaceMenu = playerSettings[multiplayer ? 0 : player.playernum].gamepad_facehotbar; | |||
| 19816 | } | |||
| 19817 | else if ( inputs.bPlayerUsingKeyboardControl(player.playernum) ) | |||
| 19818 | { | |||
| 19819 | useHotbarFaceMenu = false; | |||
| 19820 | } | |||
| 19821 | #else | |||
| 19822 | useHotbarFaceMenu = playerSettings[multiplayer ? 0 : player.playernum].gamepad_facehotbar; | |||
| 19823 | #endif // NINTENDO | |||
| 19824 | ||||
| 19825 | if ( !hotbarFrame ) | |||
| 19826 | { | |||
| 19827 | char name[32]; | |||
| 19828 | snprintf(name, sizeof(name), "player hotbar %d", player.playernum); | |||
| 19829 | hotbarFrame = player.hud.hudFrame->addFrame(name); | |||
| 19830 | hotbarFrame->setHollow(true); | |||
| 19831 | hotbarFrame->setBorder(0); | |||
| 19832 | hotbarFrame->setOwner(player.playernum); | |||
| 19833 | hotbarFrame->setInheritParentFrameOpacity(false); | |||
| 19834 | createHotbar(player.playernum); | |||
| 19835 | } | |||
| 19836 | hotbarFrame->setSize(SDL_Rect{ 0, 0, | |||
| 19837 | players[player.playernum]->camera_virtualWidth(), | |||
| 19838 | players[player.playernum]->camera_virtualHeight() }); | |||
| 19839 | ||||
| 19840 | if ( gamePaused || nohud || !players[player.playernum]->isLocalPlayer() ) | |||
| 19841 | { | |||
| 19842 | // hide | |||
| 19843 | hotbarFrame->setDisabled(true); | |||
| 19844 | return; | |||
| 19845 | } | |||
| 19846 | else | |||
| 19847 | { | |||
| 19848 | hotbarFrame->setDisabled(false); | |||
| 19849 | } | |||
| 19850 | ||||
| 19851 | updateHotbar(); | |||
| 19852 | } | |||
| 19853 | ||||
| 19854 | void Player::Inventory_t::Appraisal_t::updateAppraisalAnim() | |||
| 19855 | { | |||
| 19856 | /*if ( current_item == 0 ) | |||
| 19857 | { | |||
| 19858 | animAppraisal = 0.0; | |||
| 19859 | return; | |||
| 19860 | }*/ | |||
| 19861 | real_t fpsScale = getFPSScale(60.0); | |||
| 19862 | real_t scale = PI3.14159265358979323846 / 40; | |||
| 19863 | animAppraisal += fpsScale * (scale); | |||
| 19864 | if ( animAppraisal >= 4 * PI3.14159265358979323846 ) | |||
| 19865 | { | |||
| 19866 | animAppraisal -= 4 * PI3.14159265358979323846; | |||
| 19867 | } | |||
| 19868 | ||||
| 19869 | if ( itemNotifyUpdatedThisTick == 0 ) | |||
| 19870 | { | |||
| 19871 | itemNotifyUpdatedThisTick = ticks; | |||
| 19872 | itemNotifyAnimState = 0; | |||
| 19873 | } | |||
| 19874 | if ( (itemNotifyUpdatedThisTick != ticks) && (ticks - itemNotifyUpdatedThisTick) % (TICKS_PER_SECOND50 / 5) == 0 ) | |||
| 19875 | { | |||
| 19876 | if ( itemNotifyUpdatedThisTick != ticks ) | |||
| 19877 | { | |||
| 19878 | ++itemNotifyAnimState; | |||
| 19879 | itemNotifyUpdatedThisTick = ticks; | |||
| 19880 | } | |||
| 19881 | if ( itemNotifyAnimState > 2 ) | |||
| 19882 | { | |||
| 19883 | itemNotifyAnimState = 0; | |||
| 19884 | } | |||
| 19885 | } | |||
| 19886 | } | |||
| 19887 | ||||
| 19888 | void drawClockwiseSquareMesh(const char* texture, float lerp, SDL_Rect rect, Uint32 color) { | |||
| 19889 | auto image = Image::get(texture); | |||
| 19890 | image->drawClockwise(lerp, nullptr, rect, | |||
| 19891 | SDL_Rect{0, 0, Frame::virtualScreenX, Frame::virtualScreenY}, color); | |||
| 19892 | } | |||
| 19893 | ||||
| 19894 | void drawUnidentifiedItemEffectHotbarCallback(const Widget& widget, SDL_Rect rect) | |||
| 19895 | { | |||
| 19896 | const int player = widget.getOwner(); | |||
| 19897 | auto& appraisal = players[player]->inventoryUI.appraisal; | |||
| 19898 | if ( appraisal.animStartTick == ticks ) | |||
| 19899 | { | |||
| 19900 | return; | |||
| 19901 | } | |||
| 19902 | ||||
| 19903 | const Frame* parent = static_cast<const Frame*>(widget.getParent()); | |||
| 19904 | { | |||
| 19905 | SDL_Rect drawRect = rect; | |||
| 19906 | drawRect.x += 4; | |||
| 19907 | drawRect.y += 4; | |||
| 19908 | drawRect.w -= 6; | |||
| 19909 | drawRect.h -= 6; | |||
| 19910 | drawRect.x += drawRect.w / 2; | |||
| 19911 | drawRect.y += drawRect.h / 2; | |||
| 19912 | real_t opacity = 192; | |||
| 19913 | if ( parent && parent->getOpacity() < 100.0 ) | |||
| 19914 | { | |||
| 19915 | opacity *= parent->getOpacity() / 100.0; | |||
| 19916 | } | |||
| 19917 | const auto& appraisal = players[player]->inventoryUI.appraisal; | |||
| 19918 | drawClockwiseSquareMesh("images/ui/HUD/hotbar/Appraisal_Icon_OutlineHotbar.png", | |||
| 19919 | (appraisal.timermax - appraisal.timer) / (float)appraisal.timermax, | |||
| 19920 | drawRect, makeColor(255, 255, 255, opacity)); | |||
| 19921 | } | |||
| 19922 | ||||
| 19923 | auto drawMesh = [](real_t x, real_t y, real_t size, SDL_Rect rect, Uint32 color) { | |||
| 19924 | auto image = Image::get("images/ui/Inventory/Appraisal_Icon.png"); | |||
| 19925 | const real_t sx = rect.w * size; | |||
| 19926 | const real_t sy = rect.h * size; | |||
| 19927 | image->drawColor(nullptr, SDL_Rect{(int)x, (int)y, (int)sx, (int)sy}, | |||
| 19928 | SDL_Rect{0, 0, Frame::virtualScreenX, Frame::virtualScreenY}, color); | |||
| 19929 | }; | |||
| 19930 | { | |||
| 19931 | const int imgSize = 26; | |||
| 19932 | SDL_Rect drawRect = rect; | |||
| 19933 | drawRect.x += 4 + (rect.w - 6) / 2 - imgSize / 2; | |||
| 19934 | drawRect.y += 4 + (rect.h - 6) / 2 - imgSize / 2; | |||
| 19935 | int offsetSize = 7; | |||
| 19936 | int offsetx = offsetSize * cos(std::min(4 * PI3.14159265358979323846, appraisal.animAppraisal)); | |||
| 19937 | int offsety = offsetSize * sin(std::min(4 * PI3.14159265358979323846, appraisal.animAppraisal)); | |||
| 19938 | ||||
| 19939 | drawRect.w = imgSize; | |||
| 19940 | drawRect.h = imgSize; | |||
| 19941 | ||||
| 19942 | real_t opacity = 92 + 160 * fabs(sin(std::min(2 * PI3.14159265358979323846, appraisal.animAppraisal) / 2)); | |||
| 19943 | if ( parent && parent->getOpacity() < 100.0 ) | |||
| 19944 | { | |||
| 19945 | opacity *= parent->getOpacity() / 100.0; | |||
| 19946 | } | |||
| 19947 | drawMesh(drawRect.x + offsetx, drawRect.y + offsety, | |||
| 19948 | (real_t)1.0, drawRect, makeColor(255, 255, 255, opacity)); | |||
| 19949 | } | |||
| 19950 | } | |||
| 19951 | ||||
| 19952 | void drawUnidentifiedItemEffectCallback(const Widget& widget, SDL_Rect rect) | |||
| 19953 | { | |||
| 19954 | const int player = widget.getOwner(); | |||
| 19955 | auto& appraisal = players[player]->inventoryUI.appraisal; | |||
| 19956 | if ( appraisal.animStartTick == ticks ) | |||
| 19957 | { | |||
| 19958 | return; | |||
| 19959 | } | |||
| 19960 | ||||
| 19961 | const Frame* parent = static_cast<const Frame*>(widget.getParent()); | |||
| 19962 | { | |||
| 19963 | SDL_Rect drawRect = rect; | |||
| 19964 | drawRect.x += 2; | |||
| 19965 | drawRect.y += 2; | |||
| 19966 | drawRect.w -= 2; | |||
| 19967 | drawRect.h -= 2; | |||
| 19968 | drawRect.x += drawRect.w / 2; | |||
| 19969 | drawRect.y += drawRect.h / 2; | |||
| 19970 | real_t opacity = 192; | |||
| 19971 | if ( parent && parent->getOpacity() < 100.0 ) | |||
| 19972 | { | |||
| 19973 | opacity *= parent->getOpacity() / 100.0; | |||
| 19974 | } | |||
| 19975 | drawClockwiseSquareMesh("images/ui/Inventory/Appraisal_Icon_Outline.png", | |||
| 19976 | (appraisal.timermax - appraisal.timer) / (float)appraisal.timermax, | |||
| 19977 | drawRect, makeColor(255, 255, 255, opacity)); | |||
| 19978 | } | |||
| 19979 | ||||
| 19980 | auto drawMesh = [](real_t x, real_t y, real_t size, SDL_Rect rect, Uint32 color) { | |||
| 19981 | auto image = Image::get("images/ui/Inventory/Appraisal_Icon.png"); | |||
| 19982 | const real_t sx = rect.w * size; | |||
| 19983 | const real_t sy = rect.h * size; | |||
| 19984 | image->drawColor(nullptr, SDL_Rect{(int)x, (int)y, (int)sx, (int)sy}, | |||
| 19985 | SDL_Rect{0, 0, Frame::virtualScreenX, Frame::virtualScreenY}, color); | |||
| 19986 | }; | |||
| 19987 | { | |||
| 19988 | const int imgSize = 26; | |||
| 19989 | SDL_Rect drawRect = rect; | |||
| 19990 | drawRect.x += 4 + (rect.w - 6) / 2 - imgSize / 2; | |||
| 19991 | drawRect.y += 4 + (rect.h - 6) / 2 - imgSize / 2; | |||
| 19992 | int offsetSize = 7; | |||
| 19993 | int offsetx = offsetSize * cos(std::min(4 * PI3.14159265358979323846, appraisal.animAppraisal)); | |||
| 19994 | int offsety = offsetSize * sin(std::min(4 * PI3.14159265358979323846, appraisal.animAppraisal)); | |||
| 19995 | ||||
| 19996 | drawRect.w = imgSize; | |||
| 19997 | drawRect.h = imgSize; | |||
| 19998 | ||||
| 19999 | real_t opacity = 92 + 160 * fabs(sin(std::min(2 * PI3.14159265358979323846, appraisal.animAppraisal) / 2)); | |||
| 20000 | if ( parent && parent->getOpacity() < 100.0 ) | |||
| 20001 | { | |||
| 20002 | opacity *= parent->getOpacity() / 100.0; | |||
| 20003 | } | |||
| 20004 | drawMesh(drawRect.x + offsetx, drawRect.y + offsety, | |||
| 20005 | (real_t)1.0, drawRect, makeColor(255, 255, 255, opacity)); | |||
| 20006 | } | |||
| 20007 | } | |||
| 20008 | ||||
| 20009 | void createPlayerInventorySlotFrameElements(Frame* slotFrame) | |||
| 20010 | { | |||
| 20011 | const SDL_Rect slotSize = SDL_Rect{ 0, 0, slotFrame->getSize().w, slotFrame->getSize().h }; | |||
| 20012 | SDL_Rect coloredBackgroundPos = SDL_Rect{ slotSize.x + 2, slotSize.y + 2, slotSize.w - 2, slotSize.h - 2 }; | |||
| 20013 | ||||
| 20014 | auto beatitudeFrame = slotFrame->addFrame("beatitude status frame"); // covers unidentified status as well | |||
| 20015 | beatitudeFrame->setSize(slotSize); | |||
| 20016 | beatitudeFrame->setHollow(true); | |||
| 20017 | beatitudeFrame->setDisabled(true); | |||
| 20018 | beatitudeFrame->addImage(coloredBackgroundPos, 0xFFFFFFFF, "images/system/white.png", "beatitude status bg"); | |||
| 20019 | ||||
| 20020 | auto brokenStatusFrame = slotFrame->addFrame("broken status frame"); | |||
| 20021 | brokenStatusFrame->setSize(slotSize); | |||
| 20022 | brokenStatusFrame->setHollow(true); | |||
| 20023 | brokenStatusFrame->setDisabled(true); | |||
| 20024 | brokenStatusFrame->addImage(coloredBackgroundPos, makeColor( 160, 160, 160, 64), "images/system/white.png", "broken status bg"); | |||
| 20025 | ||||
| 20026 | auto itemSpriteFrame = slotFrame->addFrame("item sprite frame"); | |||
| 20027 | ||||
| 20028 | // cut off the slot 2px borders | |||
| 20029 | SDL_Rect itemSpriteBorder = { slotSize.x + 2, slotSize.y + 2, slotFrame->getSize().w - 2, slotFrame->getSize().h - 2 }; | |||
| 20030 | const int itemSpriteSize = players[slotFrame->getOwner()]->inventoryUI.getItemSpriteSize(); | |||
| 20031 | const int alignOffset = (itemSpriteBorder.w - itemSpriteSize) / 2; // align the item sprite within the box by this offset to center | |||
| 20032 | itemSpriteBorder.x += alignOffset; | |||
| 20033 | itemSpriteBorder.y += alignOffset; | |||
| 20034 | itemSpriteBorder.w = itemSpriteSize; | |||
| 20035 | itemSpriteBorder.h = itemSpriteSize; | |||
| 20036 | ||||
| 20037 | itemSpriteFrame->setSize(SDL_Rect{ itemSpriteBorder.x, itemSpriteBorder.y, | |||
| 20038 | itemSpriteBorder.w, itemSpriteBorder.h }); | |||
| 20039 | itemSpriteFrame->setHollow(true); | |||
| 20040 | itemSpriteFrame->setDisabled(true); | |||
| 20041 | SDL_Rect imgPos{ 0, 0, itemSpriteFrame->getSize().w, itemSpriteFrame->getSize().h }; | |||
| 20042 | auto img = itemSpriteFrame->addImage(imgPos, 0xFFFFFFFF, "images/system/white.png", "item sprite img"); | |||
| 20043 | img->outline = false; | |||
| 20044 | img->outlineColor = 0; | |||
| 20045 | auto iconLabelBgImg = itemSpriteFrame->addImage(SDL_Rect{ 0, 0, 16, 16 }, 0xFFFFFFFF, | |||
| 20046 | "images/ui/Inventory/Icon_Label_Backing_00.png", "icon label bg img"); | |||
| 20047 | iconLabelBgImg->disabled = true; | |||
| 20048 | ||||
| 20049 | auto iconLabelImg = itemSpriteFrame->addImage(SDL_Rect{ 0, 0, 16, 16 }, 0xFFFFFFFF, | |||
| 20050 | "", "icon label img"); | |||
| 20051 | iconLabelImg->disabled = true; | |||
| 20052 | ||||
| 20053 | auto unusableFrame = slotFrame->addFrame("unusable item frame"); | |||
| 20054 | unusableFrame->setSize(slotSize); | |||
| 20055 | unusableFrame->setHollow(true); | |||
| 20056 | unusableFrame->setDisabled(true); | |||
| 20057 | unusableFrame->addImage(coloredBackgroundPos, makeColor( 64, 64, 64, 144), "images/system/white.png", "unusable item bg"); | |||
| 20058 | ||||
| 20059 | auto appraisalFrame = slotFrame->addFrame("appraisal frame"); | |||
| 20060 | appraisalFrame->setSize(slotSize); | |||
| 20061 | appraisalFrame->setHollow(true); | |||
| 20062 | appraisalFrame->setDisabled(true); | |||
| 20063 | appraisalFrame->addImage(SDL_Rect{ 4, 4, 6, 14 }, 0xFFFFFFFF, | |||
| 20064 | "images/ui/Inventory/tooltips/ExclamationAnim00.png", "new notif img"); | |||
| 20065 | ||||
| 20066 | static const char* qtyfont = "fonts/pixel_maz.ttf#32#2"; | |||
| 20067 | auto quantityFrame = slotFrame->addFrame("quantity frame"); | |||
| 20068 | quantityFrame->setSize(slotSize); | |||
| 20069 | quantityFrame->setHollow(true); | |||
| 20070 | Field* qtyText = quantityFrame->addField("quantity text", 32); | |||
| 20071 | qtyText->setFont(qtyfont); | |||
| 20072 | qtyText->setColor(0xffffffff); | |||
| 20073 | qtyText->setHJustify(Field::justify_t::BOTTOM); | |||
| 20074 | qtyText->setVJustify(Field::justify_t::RIGHT); | |||
| 20075 | qtyText->setText("10"); | |||
| 20076 | qtyText->setSize(SDL_Rect{ 0, 6, quantityFrame->getSize().w, quantityFrame->getSize().h }); | |||
| 20077 | ||||
| 20078 | auto equippedIconFrame = slotFrame->addFrame("equipped icon frame"); | |||
| 20079 | equippedIconFrame->setSize(slotSize); | |||
| 20080 | equippedIconFrame->setHollow(true); | |||
| 20081 | SDL_Rect equippedImgPos = { 2, slotSize.h - 18, 18, 18 }; | |||
| 20082 | equippedIconFrame->addImage(equippedImgPos, 0xFFFFFFFF, "images/system/Equipped.png", "equipped icon img"); | |||
| 20083 | ||||
| 20084 | auto brokenIconFrame = slotFrame->addFrame("broken icon frame"); | |||
| 20085 | brokenIconFrame->setSize(slotSize); | |||
| 20086 | brokenIconFrame->setHollow(true); | |||
| 20087 | brokenIconFrame->addImage(equippedImgPos, 0xFFFFFFFF, "images/system/Broken.png", "broken icon img"); | |||
| 20088 | } | |||
| 20089 | ||||
| 20090 | void resetInventorySlotFrames(const int player) | |||
| 20091 | { | |||
| 20092 | //for ( int x = 0; x < players[player]->inventoryUI.getSizeX(); ++x ) | |||
| 20093 | //{ | |||
| 20094 | // for ( int y = Player::Inventory_t::PaperDollRows::DOLL_ROW_1; y < players[player]->inventoryUI.DEFAULT_INVENTORY_SIZEY + players[player]->inventoryUI.getPlayerBackpackBonusSizeY(); ++y ) | |||
| 20095 | // { | |||
| 20096 | // if ( auto slotFrame = players[player]->inventoryUI.getInventorySlotFrame(x, y) ) | |||
| 20097 | // { | |||
| 20098 | // slotFrame->setDisabled(true); | |||
| 20099 | // } | |||
| 20100 | // } | |||
| 20101 | //} | |||
| 20102 | ||||
| 20103 | if ( players[player]->inventoryUI.frame ) | |||
| 20104 | { | |||
| 20105 | for ( auto& pair : players[player]->inventoryUI.slotFrames ) | |||
| 20106 | { | |||
| 20107 | if ( pair.second ) { pair.second->setDisabled(true); } | |||
| 20108 | } | |||
| 20109 | } | |||
| 20110 | ||||
| 20111 | //for ( int x = 0; x < Player::Inventory_t::MAX_SPELLS_X; ++x ) | |||
| 20112 | //{ | |||
| 20113 | // for ( int y = 0; y < Player::Inventory_t::MAX_SPELLS_Y; ++y ) | |||
| 20114 | // { | |||
| 20115 | // if ( auto slotFrame = players[player]->inventoryUI.getSpellSlotFrame(x, y) ) | |||
| 20116 | // { | |||
| 20117 | // slotFrame->setDisabled(true); | |||
| 20118 | // } | |||
| 20119 | // } | |||
| 20120 | //} | |||
| 20121 | ||||
| 20122 | if ( players[player]->inventoryUI.spellFrame ) | |||
| 20123 | { | |||
| 20124 | for ( auto& pair : players[player]->inventoryUI.spellSlotFrames ) | |||
| 20125 | { | |||
| 20126 | if ( pair.second ) { pair.second->setDisabled(true); } | |||
| 20127 | } | |||
| 20128 | } | |||
| 20129 | ||||
| 20130 | //for ( int x = 0; x < Player::Inventory_t::MAX_CHEST_X; ++x ) | |||
| 20131 | //{ | |||
| 20132 | // for ( int y = 0; y < Player::Inventory_t::MAX_CHEST_Y; ++y ) | |||
| 20133 | // { | |||
| 20134 | // if ( auto slotFrame = players[player]->inventoryUI.getChestSlotFrame(x, y) ) | |||
| 20135 | // { | |||
| 20136 | // slotFrame->setDisabled(true); | |||
| 20137 | // } | |||
| 20138 | // } | |||
| 20139 | //} | |||
| 20140 | ||||
| 20141 | if ( players[player]->inventoryUI.chestFrame ) | |||
| 20142 | { | |||
| 20143 | for ( auto& pair : players[player]->inventoryUI.chestSlotFrames ) | |||
| 20144 | { | |||
| 20145 | if ( pair.second ) { pair.second->setDisabled(true); } | |||
| 20146 | } | |||
| 20147 | } | |||
| 20148 | ||||
| 20149 | //for ( int x = 0; x < Player::ShopGUI_t::MAX_SHOP_X; ++x ) | |||
| 20150 | //{ | |||
| 20151 | // for ( int y = 0; y < Player::ShopGUI_t::MAX_SHOP_Y; ++y ) | |||
| 20152 | // { | |||
| 20153 | // if ( auto slotFrame = players[player]->shopGUI.getShopSlotFrame(x, y) ) | |||
| 20154 | // { | |||
| 20155 | // slotFrame->setDisabled(true); | |||
| 20156 | // } | |||
| 20157 | // } | |||
| 20158 | //} | |||
| 20159 | ||||
| 20160 | if ( players[player]->shopGUI.shopFrame ) | |||
| 20161 | { | |||
| 20162 | for ( auto& pair : players[player]->shopGUI.shopSlotFrames ) | |||
| 20163 | { | |||
| 20164 | if ( pair.second ) { pair.second->setDisabled(true); } | |||
| 20165 | } | |||
| 20166 | } | |||
| 20167 | } | |||
| 20168 | ||||
| 20169 | bool getSlotFrameXYFromMousePos(const int player, int& outx, int& outy, bool spells) | |||
| 20170 | { | |||
| 20171 | if ( !gui ) | |||
| 20172 | { | |||
| 20173 | return false; | |||
| 20174 | } | |||
| 20175 | ||||
| 20176 | if ( players[player]->inventoryUI.chestFrame && !spells | |||
| 20177 | && !players[player]->inventoryUI.chestFrame->isDisabled() ) | |||
| 20178 | { | |||
| 20179 | for ( int x = 0; x < Player::Inventory_t::MAX_CHEST_X; ++x ) | |||
| 20180 | { | |||
| 20181 | for ( int y = 0; y < Player::Inventory_t::MAX_CHEST_Y; ++y ) | |||
| 20182 | { | |||
| 20183 | auto slotFrame = players[player]->inventoryUI.getChestSlotFrame(x, y); | |||
| 20184 | if ( !slotFrame ) | |||
| 20185 | { | |||
| 20186 | continue; | |||
| 20187 | } | |||
| 20188 | ||||
| 20189 | if ( !players[player]->inventoryUI.chestGUI.isSlotVisible(x, y) ) | |||
| 20190 | { | |||
| 20191 | continue; | |||
| 20192 | } | |||
| 20193 | ||||
| 20194 | if ( slotFrame->capturesMouseInRealtimeCoords() ) | |||
| 20195 | { | |||
| 20196 | outx = x; | |||
| 20197 | outy = y; | |||
| 20198 | return true; | |||
| 20199 | } | |||
| 20200 | } | |||
| 20201 | } | |||
| 20202 | } | |||
| 20203 | if ( players[player]->inventoryUI.frame && !spells | |||
| 20204 | && players[player]->inventory_mode == INVENTORY_MODE_ITEM ) | |||
| 20205 | { | |||
| 20206 | for ( int x = 0; x < players[player]->inventoryUI.getSizeX(); ++x ) | |||
| 20207 | { | |||
| 20208 | for ( int y = Player::Inventory_t::DOLL_ROW_1; y < players[player]->inventoryUI.getSizeY(); ++y ) | |||
| 20209 | { | |||
| 20210 | auto slotFrame = players[player]->inventoryUI.getInventorySlotFrame(x, y); | |||
| 20211 | if ( !slotFrame ) | |||
| 20212 | { | |||
| 20213 | continue; | |||
| 20214 | } | |||
| 20215 | ||||
| 20216 | if ( slotFrame->capturesMouseInRealtimeCoords() ) | |||
| 20217 | { | |||
| 20218 | outx = x; | |||
| 20219 | outy = y; | |||
| 20220 | return true; | |||
| 20221 | } | |||
| 20222 | } | |||
| 20223 | } | |||
| 20224 | } | |||
| 20225 | if ( players[player]->inventoryUI.spellFrame && spells | |||
| 20226 | && players[player]->inventory_mode == INVENTORY_MODE_SPELL ) | |||
| 20227 | { | |||
| 20228 | for ( int x = 0; x < Player::Inventory_t::MAX_SPELLS_X; ++x ) | |||
| 20229 | { | |||
| 20230 | for ( int y = 0; y < Player::Inventory_t::MAX_SPELLS_Y; ++y ) | |||
| 20231 | { | |||
| 20232 | auto slotFrame = players[player]->inventoryUI.getSpellSlotFrame(x, y); | |||
| 20233 | if ( !slotFrame ) | |||
| 20234 | { | |||
| 20235 | continue; | |||
| 20236 | } | |||
| 20237 | ||||
| 20238 | if ( !players[player]->inventoryUI.spellPanel.isSlotVisible(x, y) ) | |||
| 20239 | { | |||
| 20240 | continue; | |||
| 20241 | } | |||
| 20242 | ||||
| 20243 | if ( slotFrame->capturesMouseInRealtimeCoords() ) | |||
| 20244 | { | |||
| 20245 | outx = x; | |||
| 20246 | outy = y; | |||
| 20247 | return true; | |||
| 20248 | } | |||
| 20249 | } | |||
| 20250 | } | |||
| 20251 | } | |||
| 20252 | return false; | |||
| 20253 | } | |||
| 20254 | ||||
| 20255 | enum SlotFrameIndices : size_t { | |||
| 20256 | SLOTFRAME_BEATITUDE_FRAME = 0, | |||
| 20257 | SLOTFRAME_BEATITUDE_IMG = 0, | |||
| 20258 | SLOTFRAME_BROKEN_STATUS_FRAME = 1, | |||
| 20259 | SLOTFRAME_BROKEN_STATUS_IMG = 0, | |||
| 20260 | SLOTFRAME_ITEMSPRITE_FRAME = 2, | |||
| 20261 | SLOTFRAME_ITEMSPRITE_IMG = 0, | |||
| 20262 | SLOTFRAME_ITEMSPRITE_LABELBG_IMG = 1, | |||
| 20263 | SLOTFRAME_ITEMSPRITE_LABEL_IMG = 2, | |||
| 20264 | SLOTFRAME_UNUSABLE_ITEM_FRAME = 3, | |||
| 20265 | SLOTFRAME_UNUSABLE_IMG = 0, | |||
| 20266 | SLOTFRAME_APPRAISAL_FRAME = 4, | |||
| 20267 | SLOTFRAME_APPRAISAL_NOTIF_IMG = 0, | |||
| 20268 | SLOTFRAME_QTY_FRAME = 5, | |||
| 20269 | SLOTFRAME_QTY_TEXT = 0, | |||
| 20270 | SLOTFRAME_EQUIPPED_FRAME = 6, | |||
| 20271 | SLOTFRAME_EQUIPPED_IMG = 0, | |||
| 20272 | SLOTFRAME_BROKEN_ICON_FRAME = 7, | |||
| 20273 | SLOTFRAME_BROKEN_ICON_IMG = 0 | |||
| 20274 | }; | |||
| 20275 | void updateSlotFrameFromItem(Frame* slotFrame, void* itemPtr, bool forceUnusable) | |||
| 20276 | { | |||
| 20277 | if ( !itemPtr || !slotFrame ) | |||
| 20278 | { | |||
| 20279 | return; | |||
| 20280 | } | |||
| 20281 | ||||
| 20282 | Item* item = (Item*)itemPtr; | |||
| 20283 | ||||
| 20284 | int player = slotFrame->getOwner(); | |||
| 20285 | ||||
| 20286 | bool hiddenItemInGUI = false; | |||
| 20287 | if ( item->itemSpecialShopConsumable ) | |||
| 20288 | { | |||
| 20289 | if ( stats[player]->getModifiedProficiency(PRO_TRADING) + statGetCHR(stats[player], players[player]->entity) < (((int)item->itemRequireTradingSkillInShop) * SHOP_CONSUMABLE_SKILL_REQ_PER_POINT) ) | |||
| 20290 | { | |||
| 20291 | hiddenItemInGUI = true; | |||
| 20292 | } | |||
| 20293 | } | |||
| 20294 | ||||
| 20295 | slotFrame->setDisabled(false); | |||
| 20296 | ||||
| 20297 | auto& frames = slotFrame->getFrames(); | |||
| 20298 | ||||
| 20299 | auto spriteImageFrame = frames[SLOTFRAME_ITEMSPRITE_FRAME]; // slotFrame->findFrame("item sprite frame"); | |||
| 20300 | auto spriteImage = spriteImageFrame->getImages()[SLOTFRAME_ITEMSPRITE_IMG]; // [spriteImageFrame->findImage("item sprite img"); | |||
| 20301 | ||||
| 20302 | if ( hiddenItemInGUI ) | |||
| 20303 | { | |||
| 20304 | spriteImage->path = ("*#images/system/unknownitem.png"); | |||
| 20305 | } | |||
| 20306 | else | |||
| 20307 | { | |||
| 20308 | spriteImage->path = getItemSpritePath(player, *item); | |||
| 20309 | } | |||
| 20310 | bool disableBackgrounds = false; | |||
| 20311 | if ( !strcmp(slotFrame->getName(), "dragging inventory item") ) // dragging item, no need for colors | |||
| 20312 | { | |||
| 20313 | disableBackgrounds = true; | |||
| 20314 | } | |||
| 20315 | ||||
| 20316 | int* slotType = nullptr; | |||
| 20317 | if ( slotFrame->getUserData() ) | |||
| 20318 | { | |||
| 20319 | slotType = (int*)slotFrame->getUserData(); | |||
| 20320 | if ( *slotType == GAMEUI_FRAMEDATA_ANIMATING_ITEM | |||
| 20321 | || *slotType == GAMEUI_FRAMEDATA_ALCHEMY_RECIPE_SLOT ) | |||
| 20322 | { | |||
| 20323 | disableBackgrounds = true; | |||
| 20324 | } | |||
| 20325 | } | |||
| 20326 | ||||
| 20327 | bool isHotbarIcon = false; | |||
| 20328 | bool alchemyResultIcon = &GenericGUI[player].alchemyGUI.alchemyResultPotion == item; | |||
| 20329 | if ( spriteImage->path != "" ) | |||
| 20330 | { | |||
| 20331 | spriteImageFrame->setDisabled(false); | |||
| 20332 | if ( inputs.getUIInteraction(player)->selectedItem == item ) | |||
| 20333 | { | |||
| 20334 | if ( !strcmp(slotFrame->getName(), "hotbar slot item") ) // hotbar slots | |||
| 20335 | { | |||
| 20336 | // fade this icon | |||
| 20337 | spriteImage->color = makeColor( 255, 255, 255, 128); | |||
| 20338 | disableBackgrounds = true; | |||
| 20339 | isHotbarIcon = true; | |||
| 20340 | } | |||
| 20341 | } | |||
| 20342 | else if ( !strcmp(slotFrame->getName(), "hotbar slot item") ) // hotbar slots | |||
| 20343 | { | |||
| 20344 | isHotbarIcon = true; | |||
| 20345 | auto& hotbar_t = players[player]->hotbar; | |||
| 20346 | bool tryDimHotbarSlot = false; | |||
| 20347 | if ( hotbar_t.useHotbarFaceMenu && hotbar_t.faceMenuButtonHeld != Player::Hotbar_t::GROUP_NONE ) | |||
| 20348 | { | |||
| 20349 | tryDimHotbarSlot = true; | |||
| 20350 | } | |||
| 20351 | spriteImage->color = 0xFFFFFFFF; | |||
| 20352 | if ( tryDimHotbarSlot ) | |||
| 20353 | { | |||
| 20354 | std::string hotbarSlotParentStr = slotFrame->getParent()->getName(); | |||
| 20355 | if ( hotbarSlotParentStr.find("hotbar slot ") != std::string::npos ) | |||
| 20356 | { | |||
| 20357 | int num = stoi(hotbarSlotParentStr.substr(strlen("hotbar slot "))); | |||
| 20358 | if ( hotbar_t.faceMenuButtonHeld != hotbar_t.getFaceMenuGroupForSlot(num) ) | |||
| 20359 | { | |||
| 20360 | // fade this icon | |||
| 20361 | spriteImage->color = makeColor( 255, 255, 255, 128); | |||
| 20362 | } | |||
| 20363 | } | |||
| 20364 | } | |||
| 20365 | } | |||
| 20366 | else | |||
| 20367 | { | |||
| 20368 | spriteImage->color = 0xFFFFFFFF; | |||
| 20369 | } | |||
| 20370 | if ( auto iconLabelImg = spriteImageFrame->getImages()[SLOTFRAME_ITEMSPRITE_LABEL_IMG]/*spriteImageFrame->findImage("icon label img")*/ ) | |||
| 20371 | { | |||
| 20372 | iconLabelImg->path = ItemTooltips.getIconLabel(*item); | |||
| 20373 | iconLabelImg->disabled = true; | |||
| 20374 | const int size = 16; | |||
| 20375 | const int padx = spriteImageFrame->getSize().w / 2 - size / 2; | |||
| 20376 | iconLabelImg->pos = SDL_Rect{ spriteImageFrame->getSize().w - size - 1, | |||
| 20377 | 1 /*spriteImageFrame->getSize().h - size*/, size, size }; | |||
| 20378 | if ( iconLabelImg->path != "" ) | |||
| 20379 | { | |||
| 20380 | iconLabelImg->disabled = (!item->identified || hiddenItemInGUI); | |||
| 20381 | } | |||
| 20382 | iconLabelImg->color = spriteImage->color; | |||
| 20383 | if ( auto iconLabelBgImg = spriteImageFrame->getImages()[SLOTFRAME_ITEMSPRITE_LABELBG_IMG]/*spriteImageFrame->findImage("icon label bg img")*/ ) | |||
| 20384 | { | |||
| 20385 | iconLabelBgImg->pos.w = 24; | |||
| 20386 | iconLabelBgImg->pos.h = iconLabelBgImg->pos.w; | |||
| 20387 | iconLabelBgImg->pos.x = spriteImageFrame->getSize().w - iconLabelBgImg->pos.w - 1; | |||
| 20388 | iconLabelBgImg->pos.y = 1; | |||
| 20389 | iconLabelBgImg->disabled = iconLabelImg->disabled || disableBackgrounds; | |||
| 20390 | iconLabelBgImg->color = makeColor(255, 255, 255, 255); | |||
| 20391 | } | |||
| 20392 | } | |||
| 20393 | if ( slotFrame->getUserData() ) | |||
| 20394 | { | |||
| 20395 | if ( *slotType == GAMEUI_FRAMEDATA_ALCHEMY_ITEM || *slotType == GAMEUI_FRAMEDATA_ALCHEMY_RECIPE_SLOT ) | |||
| 20396 | { | |||
| 20397 | SDL_Color color; | |||
| 20398 | getColor(spriteImage->color, &color.r, &color.g, &color.b, &color.a); | |||
| 20399 | color.a /= 2; | |||
| 20400 | spriteImage->color = makeColor(color.r, color.g, color.b, color.a); | |||
| 20401 | } | |||
| 20402 | } | |||
| 20403 | } | |||
| 20404 | ||||
| 20405 | if ( auto qtyFrame = frames[SLOTFRAME_QTY_FRAME]/*slotFrame->findFrame("quantity frame")*/ ) | |||
| 20406 | { | |||
| 20407 | qtyFrame->setDisabled(true); | |||
| 20408 | bool drawQty = (item->count > 1) ? true : false; | |||
| 20409 | if ( !drawQty && GenericGUI[player].isNodeTinkeringCraftableItem(item->node) ) | |||
| 20410 | { | |||
| 20411 | drawQty = true; | |||
| 20412 | } | |||
| 20413 | else if ( slotType && *slotType == GAMEUI_FRAMEDATA_ALCHEMY_RECIPE_ENTRY ) | |||
| 20414 | { | |||
| 20415 | drawQty = true; | |||
| 20416 | } | |||
| 20417 | Uint32 qtyColor = 0xFFFFFFFF; | |||
| 20418 | bool stackable = false; | |||
| 20419 | Item*& selectedItem = inputs.getUIInteraction(player)->selectedItem; | |||
| 20420 | if ( selectedItem && !isHotbarIcon && !alchemyResultIcon | |||
| 20421 | && !(slotType | |||
| 20422 | && (*slotType == GAMEUI_FRAMEDATA_ANIMATING_ITEM | |||
| 20423 | || *slotType == GAMEUI_FRAMEDATA_ALCHEMY_RECIPE_SLOT | |||
| 20424 | || *slotType == GAMEUI_FRAMEDATA_ALCHEMY_RECIPE_ENTRY)) ) | |||
| 20425 | { | |||
| 20426 | if ( item != selectedItem | |||
| 20427 | && !itemIsEquipped(selectedItem, player) | |||
| 20428 | && !itemIsEquipped(item, player) ) | |||
| 20429 | { | |||
| 20430 | int selectedItemQty; | |||
| 20431 | int destItemQty; | |||
| 20432 | auto result = getItemStackingBehavior(player, selectedItem, item, selectedItemQty, destItemQty); | |||
| 20433 | if ( result.resultType == ITEM_ADDED_ENTIRELY_TO_DESTINATION_STACK | |||
| 20434 | || result.resultType == ITEM_ADDED_PARTIALLY_TO_DESTINATION_STACK ) | |||
| 20435 | { | |||
| 20436 | drawQty = true; | |||
| 20437 | qtyColor = hudColors.characterSheetGreen; | |||
| 20438 | stackable = true; | |||
| 20439 | } | |||
| 20440 | } | |||
| 20441 | } | |||
| 20442 | if ( drawQty ) | |||
| 20443 | { | |||
| 20444 | qtyFrame->setDisabled(false); | |||
| 20445 | if ( auto qtyText = qtyFrame->getFields()[SLOTFRAME_QTY_TEXT]/*qtyFrame->findField("quantity text")*/ ) | |||
| 20446 | { | |||
| 20447 | char qtybuf[32] = ""; | |||
| 20448 | if ( stackable ) | |||
| 20449 | { | |||
| 20450 | if ( item->count == 1 ) | |||
| 20451 | { | |||
| 20452 | snprintf(qtybuf, sizeof(qtybuf), "+"); | |||
| 20453 | } | |||
| 20454 | else if ( item->count > 1 ) | |||
| 20455 | { | |||
| 20456 | snprintf(qtybuf, sizeof(qtybuf), "%d+", item->count); | |||
| 20457 | } | |||
| 20458 | } | |||
| 20459 | else | |||
| 20460 | { | |||
| 20461 | snprintf(qtybuf, sizeof(qtybuf), "%d", item->count); | |||
| 20462 | } | |||
| 20463 | if ( strcmp(qtyText->getText(), qtybuf) ) | |||
| 20464 | { | |||
| 20465 | qtyText->setText(qtybuf); | |||
| 20466 | } | |||
| 20467 | qtyText->setColor(qtyColor); | |||
| 20468 | } | |||
| 20469 | } | |||
| 20470 | } | |||
| 20471 | ||||
| 20472 | if ( auto beatitudeFrame = frames[SLOTFRAME_BEATITUDE_FRAME]/*slotFrame->findFrame("beatitude status frame")*/ ) | |||
| 20473 | { | |||
| 20474 | beatitudeFrame->setDisabled(true); | |||
| 20475 | //spriteImage->outline = false; | |||
| 20476 | if ( !disableBackgrounds ) | |||
| 20477 | { | |||
| 20478 | if ( auto beatitudeImg = beatitudeFrame->getImages()[SLOTFRAME_BEATITUDE_IMG]/*beatitudeFrame->findImage("beatitude status bg")*/ ) | |||
| 20479 | { | |||
| 20480 | if ( !item->identified ) | |||
| 20481 | { | |||
| 20482 | //beatitudeImg->color = makeColor( 128, 128, 0, 125); | |||
| 20483 | if ( !(slotFrame->getUserData() && *slotType == GAMEUI_FRAMEDATA_SHOP_ITEM) ) | |||
| 20484 | { | |||
| 20485 | beatitudeFrame->setDisabled(false); | |||
| 20486 | } | |||
| 20487 | //spriteImage->outlineColor = makeColor(210, 183, 76, 255); | |||
| 20488 | //spriteImage->outline = true; | |||
| 20489 | } | |||
| 20490 | else if ( item->beatitude < 0 ) | |||
| 20491 | { | |||
| 20492 | //beatitudeImg->color = makeColor( 128, 0, 0, 125); | |||
| 20493 | beatitudeFrame->setDisabled(false); | |||
| 20494 | //spriteImage->outlineColor = hudColors.characterSheetRed; | |||
| 20495 | //spriteImage->outline = true; | |||
| 20496 | } | |||
| 20497 | else if ( item->beatitude > 0 ) | |||
| 20498 | { | |||
| 20499 | /*if ( colorblind ) | |||
| 20500 | { | |||
| 20501 | beatitudeImg->color = makeColor( 100, 245, 255, 65); | |||
| 20502 | } | |||
| 20503 | else | |||
| 20504 | { | |||
| 20505 | beatitudeImg->color = makeColor( 0, 255, 0, 65); | |||
| 20506 | }*/ | |||
| 20507 | //spriteImage->outlineColor = hudColors.characterSheetHeadingText; | |||
| 20508 | //spriteImage->outline = true; | |||
| 20509 | beatitudeFrame->setDisabled(false); | |||
| 20510 | } | |||
| 20511 | /*if ( !spriteImage->outline ) | |||
| 20512 | { | |||
| 20513 | spriteImage->outlineColor = 0; | |||
| 20514 | } | |||
| 20515 | else | |||
| 20516 | { | |||
| 20517 | spriteImage->outlineColor = makeColor(0, 0, 0, 255); | |||
| 20518 | }*/ | |||
| 20519 | if ( !beatitudeFrame->isDisabled() ) | |||
| 20520 | { | |||
| 20521 | //beatitudeImg->color = uint32ColorWhite; | |||
| 20522 | if ( isHotbarIcon || (slotFrame->getUserData() && *slotType == GAMEUI_FRAMEDATA_WORLDTOOLTIP_ITEM) ) | |||
| 20523 | { | |||
| 20524 | if ( !item->identified ) | |||
| 20525 | { | |||
| 20526 | static const char* unidentifyHotbarPath = "*#images/ui/HUD/hotbar/HUD_Quickbar_Slot_Box_Overlay_App01.png"; | |||
| 20527 | if ( strcmp(unidentifyHotbarPath, beatitudeImg->path.c_str()) ) | |||
| 20528 | { | |||
| 20529 | beatitudeImg->path = unidentifyHotbarPath; | |||
| 20530 | } | |||
| 20531 | } | |||
| 20532 | else if ( item->beatitude > 0 ) | |||
| 20533 | { | |||
| 20534 | static const char* blessHotbarPath = "*#images/ui/HUD/hotbar/HUD_Quickbar_Slot_Box_Overlay_Bless01.png"; | |||
| 20535 | if ( strcmp(blessHotbarPath, beatitudeImg->path.c_str()) ) | |||
| 20536 | { | |||
| 20537 | beatitudeImg->path = blessHotbarPath; | |||
| 20538 | } | |||
| 20539 | } | |||
| 20540 | else if ( item->beatitude < 0 ) | |||
| 20541 | { | |||
| 20542 | static const char* curseHotbarPath = "*#images/ui/HUD/hotbar/HUD_Quickbar_Slot_Box_Overlay_Curse01.png"; | |||
| 20543 | if ( strcmp(curseHotbarPath, beatitudeImg->path.c_str()) ) | |||
| 20544 | { | |||
| 20545 | beatitudeImg->path = curseHotbarPath; | |||
| 20546 | } | |||
| 20547 | } | |||
| 20548 | } | |||
| 20549 | else | |||
| 20550 | { | |||
| 20551 | if ( !item->identified ) | |||
| 20552 | { | |||
| 20553 | static const char* unidentifyPath = "*#images/ui/Inventory/HUD_Inventory_Item_App00B.png"; | |||
| 20554 | if ( strcmp(unidentifyPath, beatitudeImg->path.c_str()) ) | |||
| 20555 | { | |||
| 20556 | beatitudeImg->path = unidentifyPath; | |||
| 20557 | } | |||
| 20558 | } | |||
| 20559 | else if ( item->beatitude > 0 ) | |||
| 20560 | { | |||
| 20561 | static const char* blessPath = "*#images/ui/Inventory/HUD_Inventory_Item_Bless00B.png"; | |||
| 20562 | if ( strcmp(blessPath, beatitudeImg->path.c_str()) ) | |||
| 20563 | { | |||
| 20564 | beatitudeImg->path = blessPath; | |||
| 20565 | } | |||
| 20566 | } | |||
| 20567 | else if ( item->beatitude < 0 ) | |||
| 20568 | { | |||
| 20569 | static const char* cursePath = "*#images/ui/Inventory/HUD_Inventory_Item_Curse00B.png"; | |||
| 20570 | if ( strcmp(cursePath, beatitudeImg->path.c_str()) ) | |||
| 20571 | { | |||
| 20572 | beatitudeImg->path = cursePath; | |||
| 20573 | } | |||
| 20574 | } | |||
| 20575 | } | |||
| 20576 | } | |||
| 20577 | } | |||
| 20578 | } | |||
| 20579 | } | |||
| 20580 | ||||
| 20581 | if ( auto brokenStatusFrame = frames[SLOTFRAME_BROKEN_STATUS_FRAME]/*slotFrame->findFrame("broken status frame")*/ ) | |||
| 20582 | { | |||
| 20583 | brokenStatusFrame->setDisabled(true); | |||
| 20584 | if ( !disableBackgrounds ) | |||
| 20585 | { | |||
| 20586 | if ( item->status == BROKEN ) | |||
| 20587 | { | |||
| 20588 | if ( players[player]->shopGUI.bOpen | |||
| 20589 | && isItemSellableToShop(player, item) | |||
| 20590 | && !(slotFrame->getUserData() && *slotType == GAMEUI_FRAMEDATA_SHOP_ITEM) ) | |||
| 20591 | { | |||
| 20592 | // don't grey out this item | |||
| 20593 | } | |||
| 20594 | else | |||
| 20595 | { | |||
| 20596 | brokenStatusFrame->setDisabled(false); | |||
| 20597 | auto brokenStatusImg = brokenStatusFrame->getImages()[SLOTFRAME_BROKEN_STATUS_IMG];/*brokenStatusFrame->findImage("broken status bg");*/ | |||
| 20598 | if ( isHotbarIcon || (slotFrame->getUserData() && *slotType == GAMEUI_FRAMEDATA_WORLDTOOLTIP_ITEM) ) | |||
| 20599 | { | |||
| 20600 | brokenStatusImg->path = "*#images/ui/HUD/hotbar/HUD_Quickbar_Slot_Box_Overlay_01.png"; | |||
| 20601 | } | |||
| 20602 | else | |||
| 20603 | { | |||
| 20604 | brokenStatusImg->path = "images/system/white.png"; | |||
| 20605 | } | |||
| 20606 | } | |||
| 20607 | } | |||
| 20608 | } | |||
| 20609 | } | |||
| 20610 | ||||
| 20611 | if ( auto unusableFrame = frames[SLOTFRAME_UNUSABLE_ITEM_FRAME]/*slotFrame->findFrame("unusable item frame")*/ ) | |||
| 20612 | { | |||
| 20613 | bool greyedOut = forceUnusable || hiddenItemInGUI; | |||
| 20614 | unusableFrame->setDisabled(true); | |||
| 20615 | ||||
| 20616 | if ( (slotFrame->getUserData() && *slotType == GAMEUI_FRAMEDATA_WORLDTOOLTIP_ITEM) ) | |||
| 20617 | { | |||
| 20618 | // no grey out | |||
| 20619 | } | |||
| 20620 | else if ( !disableBackgrounds ) | |||
| 20621 | { | |||
| 20622 | if ( players[player] && players[player]->entity && players[player]->entity->effectShapeshift != NOTHING ) | |||
| 20623 | { | |||
| 20624 | // shape shifted, disable some items | |||
| 20625 | if ( !item->usableWhileShapeshifted(stats[player]) ) | |||
| 20626 | { | |||
| 20627 | greyedOut = true; | |||
| 20628 | } | |||
| 20629 | } | |||
| 20630 | if ( !greyedOut && client_classes[player] == CLASS_SHAMAN | |||
| 20631 | && item->type == SPELL_ITEM && !(playerUnlockedShamanSpell(player, item)) ) | |||
| 20632 | { | |||
| 20633 | greyedOut = true; | |||
| 20634 | } | |||
| 20635 | ||||
| 20636 | if ( greyedOut ) | |||
| 20637 | { | |||
| 20638 | unusableFrame->setDisabled(false); | |||
| 20639 | } | |||
| 20640 | } | |||
| 20641 | } | |||
| 20642 | ||||
| 20643 | bool equipped = false; | |||
| 20644 | bool broken = false; | |||
| 20645 | if ( itemCategory(item) != SPELL_CAT ) | |||
| 20646 | { | |||
| 20647 | if ( itemIsEquipped(item, player) ) | |||
| 20648 | { | |||
| 20649 | equipped = true; | |||
| 20650 | } | |||
| 20651 | else if ( item->status == BROKEN ) | |||
| 20652 | { | |||
| 20653 | broken = true; | |||
| 20654 | } | |||
| 20655 | else if ( alchemyResultIcon && stats[player]->weapon | |||
| 20656 | && itemCategory(stats[player]->weapon) == POTION | |||
| 20657 | && stats[player]->weapon->identified && item->identified ) | |||
| 20658 | { | |||
| 20659 | int selectedItemQty; | |||
| 20660 | int destItemQty; | |||
| 20661 | auto result = getItemStackingBehavior(player, item, stats[player]->weapon, selectedItemQty, destItemQty); | |||
| 20662 | if ( result.resultType == ITEM_ADDED_ENTIRELY_TO_DESTINATION_STACK | |||
| 20663 | || result.resultType == ITEM_ADDED_PARTIALLY_TO_DESTINATION_STACK ) | |||
| 20664 | { | |||
| 20665 | equipped = true; | |||
| 20666 | } | |||
| 20667 | } | |||
| 20668 | } | |||
| 20669 | else | |||
| 20670 | { | |||
| 20671 | spell_t* spell = getSpellFromItem(player, item); | |||
| 20672 | if ( players[player]->magic.selectedSpell() == spell | |||
| 20673 | && (players[player]->magic.selected_spell_last_appearance == item->appearance || players[player]->magic.selected_spell_last_appearance == -1) ) | |||
| 20674 | { | |||
| 20675 | equipped = true; | |||
| 20676 | } | |||
| 20677 | } | |||
| 20678 | ||||
| 20679 | if ( auto equippedIconFrame = frames[SLOTFRAME_EQUIPPED_FRAME]/*slotFrame->findFrame("equipped icon frame")*/ ) | |||
| 20680 | { | |||
| 20681 | equippedIconFrame->setDisabled(true); | |||
| 20682 | if ( equipped && (!disableBackgrounds || (slotType && (*slotType == GAMEUI_FRAMEDATA_ANIMATING_ITEM))) ) | |||
| 20683 | { | |||
| 20684 | equippedIconFrame->setDisabled(false); | |||
| 20685 | } | |||
| 20686 | } | |||
| 20687 | if ( auto brokenIconFrame = frames[SLOTFRAME_BROKEN_ICON_FRAME]/*slotFrame->findFrame("broken icon frame")*/ ) | |||
| 20688 | { | |||
| 20689 | brokenIconFrame->setDisabled(true); | |||
| 20690 | if ( broken && (!disableBackgrounds || (slotType && (*slotType == GAMEUI_FRAMEDATA_ALCHEMY_RECIPE_SLOT))) ) | |||
| 20691 | { | |||
| 20692 | brokenIconFrame->setDisabled(false); | |||
| 20693 | } | |||
| 20694 | } | |||
| 20695 | ||||
| 20696 | if ( auto appraisalFrame = frames[SLOTFRAME_APPRAISAL_FRAME]/*slotFrame->findFrame("appraisal frame")*/ ) | |||
| 20697 | { | |||
| 20698 | appraisalFrame->setDisabled(true); | |||
| 20699 | appraisalFrame->setDrawCallback(nullptr); | |||
| 20700 | if ( !item->identified ) | |||
| 20701 | { | |||
| 20702 | appraisalFrame->setDisabled(false); | |||
| 20703 | } | |||
| 20704 | else if ( item->notifyIcon ) | |||
| 20705 | { | |||
| 20706 | appraisalFrame->setDisabled(false); | |||
| 20707 | } | |||
| 20708 | if ( !disableBackgrounds && players[player]->inventoryUI.appraisal.current_item > 0 | |||
| 20709 | && slotFrame->getOpacity() > 0.999 | |||
| 20710 | && !item->identified && item->node && item->node->list == &stats[player]->inventory | |||
| 20711 | && item->uid == players[player]->inventoryUI.appraisal.current_item ) | |||
| 20712 | { | |||
| 20713 | if ( isHotbarIcon ) | |||
| 20714 | { | |||
| 20715 | appraisalFrame->setDisabled(false); | |||
| 20716 | appraisalFrame->setDrawCallback([](const Widget& widget, SDL_Rect rect) { | |||
| 20717 | drawUnidentifiedItemEffectHotbarCallback(widget, rect); | |||
| 20718 | }); | |||
| 20719 | } | |||
| 20720 | else | |||
| 20721 | { | |||
| 20722 | appraisalFrame->setDisabled(false); | |||
| 20723 | appraisalFrame->setDrawCallback([](const Widget& widget, SDL_Rect rect) { | |||
| 20724 | drawUnidentifiedItemEffectCallback(widget, rect); | |||
| 20725 | }); | |||
| 20726 | } | |||
| 20727 | } | |||
| 20728 | if ( !appraisalFrame->isDisabled() ) | |||
| 20729 | { | |||
| 20730 | auto img = appraisalFrame->getImages()[SLOTFRAME_APPRAISAL_NOTIF_IMG];/*appraisalFrame->findImage("new notif img");*/ | |||
| 20731 | img->disabled = true; | |||
| 20732 | if ( !item->identified ) | |||
| 20733 | { | |||
| 20734 | img->disabled = false; | |||
| 20735 | img->path = "images/ui/Inventory/tooltips/Unidentified_Icon.png"; | |||
| 20736 | img->pos.x = 28; | |||
| 20737 | img->pos.y = 4; | |||
| 20738 | img->pos.w = 10; | |||
| 20739 | img->pos.h = 14; | |||
| 20740 | if ( isHotbarIcon || (slotFrame->getUserData() && *slotType == GAMEUI_FRAMEDATA_WORLDTOOLTIP_ITEM) ) | |||
| 20741 | { | |||
| 20742 | img->pos.x = 30; | |||
| 20743 | img->pos.y = 6; | |||
| 20744 | } | |||
| 20745 | } | |||
| 20746 | else if ( item->notifyIcon ) | |||
| 20747 | { | |||
| 20748 | img->pos.x = 4; | |||
| 20749 | img->pos.y = 4; | |||
| 20750 | img->pos.w = 6; | |||
| 20751 | img->pos.h = 14; | |||
| 20752 | if ( isHotbarIcon && !players[player]->hotbar.useHotbarFaceMenu ) | |||
| 20753 | { | |||
| 20754 | img->pos.x = 10; | |||
| 20755 | img->pos.y = 2; | |||
| 20756 | ||||
| 20757 | // to push to right of "10" text if we label that | |||
| 20758 | /*if ( players[player]->hotbar.slots()[NUM_HOTBAR_SLOTS - 1].item == item->uid ) | |||
| 20759 | { | |||
| 20760 | if ( slotFrame && slotFrame->getParent() && !strcmp(slotFrame->getParent()->getName(), "hotbar slot 9") ) | |||
| 20761 | { | |||
| 20762 | img->pos.x += 6; | |||
| 20763 | } | |||
| 20764 | }*/ | |||
| 20765 | } | |||
| 20766 | img->disabled = false; | |||
| 20767 | switch ( players[player]->inventoryUI.appraisal.itemNotifyAnimState ) | |||
| 20768 | { | |||
| 20769 | case 0: | |||
| 20770 | img->path = "images/ui/Inventory/tooltips/ExclamationAnim00.png"; | |||
| 20771 | break; | |||
| 20772 | case 1: | |||
| 20773 | img->path = "images/ui/Inventory/tooltips/ExclamationAnim01.png"; | |||
| 20774 | break; | |||
| 20775 | case 2: | |||
| 20776 | img->path = "images/ui/Inventory/tooltips/ExclamationAnim02.png"; | |||
| 20777 | break; | |||
| 20778 | default: | |||
| 20779 | img->path = "images/ui/Inventory/tooltips/ExclamationAnim00.png"; | |||
| 20780 | break; | |||
| 20781 | } | |||
| 20782 | } | |||
| 20783 | } | |||
| 20784 | } | |||
| 20785 | } | |||
| 20786 | ||||
| 20787 | void createInventoryTooltipFrame(const int player) | |||
| 20788 | { | |||
| 20789 | if ( !gui ) | |||
| 20790 | { | |||
| 20791 | return; | |||
| 20792 | } | |||
| 20793 | ||||
| 20794 | //const std::string headerFont = "fonts/pixelmix.ttf#14#2"; | |||
| 20795 | //const std::string bodyFont = "fonts/pixelmix.ttf#12#2"; | |||
| 20796 | const std::string headerFont = "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 20797 | const std::string bodyFont = "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 20798 | ||||
| 20799 | if ( !players[player]->inventoryUI.tooltipContainerFrame ) | |||
| 20800 | { | |||
| 20801 | char name[32]; | |||
| 20802 | snprintf(name, sizeof(name), "player tooltip container %d", player); | |||
| 20803 | players[player]->inventoryUI.tooltipContainerFrame = gameUIFrame[player]->addFrame(name); | |||
| 20804 | players[player]->inventoryUI.tooltipContainerFrame->setSize( | |||
| 20805 | SDL_Rect{ players[player]->camera_virtualx1(), | |||
| 20806 | players[player]->camera_virtualy1(), | |||
| 20807 | players[player]->camera_virtualWidth(), | |||
| 20808 | players[player]->camera_virtualHeight() }); | |||
| 20809 | players[player]->inventoryUI.tooltipContainerFrame->setHollow(true); | |||
| 20810 | players[player]->inventoryUI.tooltipContainerFrame->setDisabled(false); | |||
| 20811 | players[player]->inventoryUI.tooltipContainerFrame->setInheritParentFrameOpacity(false); | |||
| 20812 | } | |||
| 20813 | if ( !players[player]->inventoryUI.titleOnlyTooltipFrame ) | |||
| 20814 | { | |||
| 20815 | char name[32]; | |||
| 20816 | snprintf(name, sizeof(name), "player title only tooltip %d", player); | |||
| 20817 | players[player]->inventoryUI.titleOnlyTooltipFrame = players[player]->inventoryUI.tooltipContainerFrame->addFrame(name); | |||
| 20818 | auto tooltipFrame = players[player]->inventoryUI.titleOnlyTooltipFrame; | |||
| 20819 | tooltipFrame->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 20820 | tooltipFrame->setHollow(true); | |||
| 20821 | tooltipFrame->setDisabled(true); | |||
| 20822 | tooltipFrame->setInheritParentFrameOpacity(false); | |||
| 20823 | ||||
| 20824 | auto tooltipTextField = tooltipFrame->addField("title only header", 1024); | |||
| 20825 | tooltipTextField->setText("Nothing"); | |||
| 20826 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 20827 | tooltipTextField->setFont(headerFont.c_str()); | |||
| 20828 | tooltipTextField->setHJustify(Field::justify_t::CENTER); | |||
| 20829 | tooltipTextField->setVJustify(Field::justify_t::TOP); | |||
| 20830 | tooltipTextField->setTextColor(hudColors.characterSheetGreen); | |||
| 20831 | tooltipTextField->setPaddingPerLine(-2); | |||
| 20832 | ||||
| 20833 | Uint32 color = makeColor(255, 255, 255, 255); | |||
| 20834 | tooltipFrame->addImage(SDL_Rect{ 0, 0, tooltipFrame->getSize().w, 28 }, | |||
| 20835 | color, "*#images/ui/Inventory/tooltips/Hover_T00_TitleOnly.png", "tooltip top background"); | |||
| 20836 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 16, 28 }, | |||
| 20837 | color, "*#images/ui/Inventory/tooltips/Hover_TL00_TitleOnly.png", "tooltip top left"); | |||
| 20838 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 16, 28 }, | |||
| 20839 | color, "*#images/ui/Inventory/tooltips/Hover_TR00_TitleOnly.png", "tooltip top right"); | |||
| 20840 | } | |||
| 20841 | if ( !players[player]->inventoryUI.tooltipFrame ) | |||
| 20842 | { | |||
| 20843 | char name[32]; | |||
| 20844 | snprintf(name, sizeof(name), "player tooltip %d", player); | |||
| 20845 | players[player]->inventoryUI.tooltipFrame = players[player]->inventoryUI.tooltipContainerFrame->addFrame(name); | |||
| 20846 | auto tooltipFrame = players[player]->inventoryUI.tooltipFrame; | |||
| 20847 | tooltipFrame->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 20848 | tooltipFrame->setHollow(true); | |||
| 20849 | tooltipFrame->setDisabled(true); | |||
| 20850 | tooltipFrame->setInheritParentFrameOpacity(false); | |||
| 20851 | } | |||
| 20852 | else | |||
| 20853 | { | |||
| 20854 | return; | |||
| 20855 | } | |||
| 20856 | ||||
| 20857 | auto tooltipFrame = players[player]->inventoryUI.tooltipFrame; | |||
| 20858 | ||||
| 20859 | Uint32 color = makeColor( 255, 255, 255, 255); | |||
| 20860 | tooltipFrame->addImage(SDL_Rect{ 0, 0, tooltipFrame->getSize().w, 28 }, | |||
| 20861 | color, "*#images/ui/Inventory/tooltips/Hover_T00.png", "tooltip top background"); | |||
| 20862 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 16, 28 }, | |||
| 20863 | color, "*#images/ui/Inventory/tooltips/Hover_TL00.png", "tooltip top left"); | |||
| 20864 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 16, 28 }, | |||
| 20865 | color, "*#images/ui/Inventory/tooltips/Hover_TR00.png", "tooltip top right"); | |||
| 20866 | ||||
| 20867 | tooltipFrame->addImage(SDL_Rect{ 0, 0, tooltipFrame->getSize().w, 52 }, | |||
| 20868 | color, "*#images/ui/Inventory/tooltips/Hover_C00.png", "tooltip middle background"); | |||
| 20869 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 16, 52 }, | |||
| 20870 | color, "*#images/ui/Inventory/tooltips/Hover_L00.png", "tooltip middle left"); | |||
| 20871 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 16, 52 }, | |||
| 20872 | color, "*#images/ui/Inventory/tooltips/Hover_R00.png", "tooltip middle right"); | |||
| 20873 | ||||
| 20874 | tooltipFrame->addImage(SDL_Rect{ 0, 0, tooltipFrame->getSize().w, 26 }, | |||
| 20875 | color, "*#images/ui/Inventory/tooltips/Hover_B00.png", "tooltip bottom background"); | |||
| 20876 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 16, 26 }, | |||
| 20877 | color, "*#images/ui/Inventory/tooltips/Hover_BL01.png", "tooltip bottom left"); | |||
| 20878 | tooltipFrame->addImage(SDL_Rect{ 0, 0, 16, 26 }, | |||
| 20879 | color, "*#images/ui/Inventory/tooltips/Hover_BR01.png", "tooltip bottom right"); | |||
| 20880 | ||||
| 20881 | auto tooltipTextField = tooltipFrame->addField("inventory mouse tooltip header", 1024); | |||
| 20882 | tooltipTextField->setText("Nothing"); | |||
| 20883 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 20884 | tooltipTextField->setFont(headerFont.c_str()); | |||
| 20885 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 20886 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 20887 | tooltipTextField->setColor(makeColor( 67, 195, 157, 255)); | |||
| 20888 | ||||
| 20889 | // temporary debug stuff | |||
| 20890 | { | |||
| 20891 | Frame::image_t* tmp = tooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 20892 | 0xFFFFFFFF, "images/system/white.png", "inventory mouse tooltip min"); | |||
| 20893 | tmp->color = makeColor( 255, 0, 0, 255); | |||
| 20894 | tmp->disabled = true; | |||
| 20895 | tmp = tooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 20896 | 0xFFFFFFFF, "images/system/white.png", "inventory mouse tooltip max"); | |||
| 20897 | tmp->color = makeColor( 0, 255, 0, 255); | |||
| 20898 | tmp->disabled = true; | |||
| 20899 | tmp = tooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 20900 | 0xFFFFFFFF, "images/system/white.png", "inventory mouse tooltip header max"); | |||
| 20901 | tmp->color = makeColor( 0, 255, 255, 255); | |||
| 20902 | tmp->disabled = true; | |||
| 20903 | tmp = tooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 20904 | 0xFFFFFFFF, "images/system/white.png", "inventory mouse tooltip header bg"); | |||
| 20905 | tmp->color = makeColor( 255, 255, 255, 255); | |||
| 20906 | tmp->disabled = true; | |||
| 20907 | tmp = tooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 20908 | 0xFFFFFFFF, "images/system/white.png", "inventory mouse tooltip header bg new"); | |||
| 20909 | tmp->color = makeColor( 255, 255, 0, 255); | |||
| 20910 | tmp->disabled = true; | |||
| 20911 | ||||
| 20912 | tmp = tooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 20913 | makeColor(255, 255, 255, 0), "images/ui/Inventory/tooltips/TooltipGradientTop.png", "inventory mouse tooltip fade top"); | |||
| 20914 | tmp->disabled = true; | |||
| 20915 | tmp->ontop = true; | |||
| 20916 | tmp = tooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 20917 | makeColor(255, 255, 255, 0), "images/ui/Inventory/tooltips/TooltipGradientBottom.png", "inventory mouse tooltip fade bottom"); | |||
| 20918 | tmp->disabled = true; | |||
| 20919 | tmp->ontop = true; | |||
| 20920 | } | |||
| 20921 | ||||
| 20922 | if ( auto attrFrame = tooltipFrame->addFrame("inventory mouse tooltip attributes frame") ) | |||
| 20923 | { | |||
| 20924 | attrFrame->setHollow(true); | |||
| 20925 | attrFrame->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 20926 | ||||
| 20927 | auto spellImageBg = attrFrame->addImage(SDL_Rect{ 0, 0, 48, 48 }, | |||
| 20928 | 0xFFFFFFFF, "*#images/ui/Inventory/tooltips/SpellBorder_00.png", "inventory mouse tooltip spell image bg"); | |||
| 20929 | spellImageBg->disabled = true; | |||
| 20930 | //spellImageBg->color = makeColor( 125, 125, 125, 228); | |||
| 20931 | auto spellImage = attrFrame->addImage(SDL_Rect{ 0, 0, 36, 36 }, | |||
| 20932 | 0xFFFFFFFF, "images/system/white.png", "inventory mouse tooltip spell image"); | |||
| 20933 | spellImage->disabled = true; | |||
| 20934 | ||||
| 20935 | attrFrame->addImage(SDL_Rect{ 0, 0, 24, 24 }, | |||
| 20936 | 0xFFFFFFFF, "*#images/ui/Inventory/tooltips/HUD_Tooltip_Icon_Damage_00.png", "inventory mouse tooltip primary image"); | |||
| 20937 | tooltipTextField = attrFrame->addField("inventory mouse tooltip primary value", 256); | |||
| 20938 | tooltipTextField->setText("Nothing"); | |||
| 20939 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 20940 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 20941 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 20942 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 20943 | tooltipTextField->setTextColor(makeColor( 188, 154, 114, 255)); | |||
| 20944 | ||||
| 20945 | tooltipTextField = attrFrame->addField("inventory mouse tooltip primary value highlight", 256); | |||
| 20946 | tooltipTextField->setText("Nothing"); | |||
| 20947 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 20948 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 20949 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 20950 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 20951 | tooltipTextField->setTextColor(makeColor( 188, 154, 114, 255)); | |||
| 20952 | ||||
| 20953 | tooltipTextField = attrFrame->addField("inventory mouse tooltip primary value positive text", 256); | |||
| 20954 | tooltipTextField->setText("Nothing"); | |||
| 20955 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 20956 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 20957 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 20958 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 20959 | tooltipTextField->setTextColor(makeColor( 188, 154, 114, 255)); | |||
| 20960 | ||||
| 20961 | tooltipTextField = attrFrame->addField("inventory mouse tooltip primary value negative text", 256); | |||
| 20962 | tooltipTextField->setText("Nothing"); | |||
| 20963 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 20964 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 20965 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 20966 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 20967 | tooltipTextField->setTextColor(makeColor( 188, 154, 114, 255)); | |||
| 20968 | ||||
| 20969 | tooltipTextField = attrFrame->addField("inventory mouse tooltip primary value slot name", 256); | |||
| 20970 | tooltipTextField->setText("Nothing"); | |||
| 20971 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 20972 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 20973 | tooltipTextField->setHJustify(Field::justify_t::RIGHT); | |||
| 20974 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 20975 | tooltipTextField->setColor(0xFFFFFFFF); | |||
| 20976 | ||||
| 20977 | attrFrame->addImage(SDL_Rect{ 0, 0, 24, 24 }, | |||
| 20978 | 0xFFFFFFFF, "images/system/con32.png", "inventory mouse tooltip secondary image"); | |||
| 20979 | tooltipTextField = attrFrame->addField("inventory mouse tooltip secondary value", 256); | |||
| 20980 | tooltipTextField->setText("Nothing"); | |||
| 20981 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 20982 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 20983 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 20984 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 20985 | tooltipTextField->setTextColor(makeColor( 188, 154, 114, 255)); | |||
| 20986 | ||||
| 20987 | tooltipTextField = attrFrame->addField("inventory mouse tooltip secondary value highlight", 256); | |||
| 20988 | tooltipTextField->setText("Nothing"); | |||
| 20989 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 20990 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 20991 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 20992 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 20993 | tooltipTextField->setTextColor(makeColor( 188, 154, 114, 255)); | |||
| 20994 | ||||
| 20995 | tooltipTextField = attrFrame->addField("inventory mouse tooltip secondary value positive text", 256); | |||
| 20996 | tooltipTextField->setText("Nothing"); | |||
| 20997 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 20998 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 20999 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 21000 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 21001 | tooltipTextField->setTextColor(makeColor( 188, 154, 114, 255)); | |||
| 21002 | ||||
| 21003 | tooltipTextField = attrFrame->addField("inventory mouse tooltip secondary value negative text", 256); | |||
| 21004 | tooltipTextField->setText("Nothing"); | |||
| 21005 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21006 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 21007 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 21008 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 21009 | tooltipTextField->setTextColor(makeColor( 188, 154, 114, 255)); | |||
| 21010 | ||||
| 21011 | attrFrame->addImage(SDL_Rect{ 0, 0, 24, 24 }, | |||
| 21012 | 0xFFFFFFFF, "images/system/con32.png", "inventory mouse tooltip third image"); | |||
| 21013 | tooltipTextField = attrFrame->addField("inventory mouse tooltip third value", 256); | |||
| 21014 | tooltipTextField->setText("Nothing"); | |||
| 21015 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21016 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 21017 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 21018 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 21019 | tooltipTextField->setTextColor(makeColor( 188, 154, 114, 255)); | |||
| 21020 | ||||
| 21021 | tooltipTextField = attrFrame->addField("inventory mouse tooltip third value highlight", 256); | |||
| 21022 | tooltipTextField->setText("Nothing"); | |||
| 21023 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21024 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 21025 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 21026 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 21027 | tooltipTextField->setTextColor(makeColor( 188, 154, 114, 255)); | |||
| 21028 | ||||
| 21029 | tooltipTextField = attrFrame->addField("inventory mouse tooltip third value positive text", 256); | |||
| 21030 | tooltipTextField->setText("Nothing"); | |||
| 21031 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21032 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 21033 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 21034 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 21035 | tooltipTextField->setTextColor(makeColor( 188, 154, 114, 255)); | |||
| 21036 | ||||
| 21037 | tooltipTextField = attrFrame->addField("inventory mouse tooltip third value negative text", 256); | |||
| 21038 | tooltipTextField->setText("Nothing"); | |||
| 21039 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21040 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 21041 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 21042 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 21043 | tooltipTextField->setTextColor(makeColor( 188, 154, 114, 255)); | |||
| 21044 | ||||
| 21045 | tooltipTextField = attrFrame->addField("inventory mouse tooltip attributes text", 1024); | |||
| 21046 | tooltipTextField->setText("Nothing"); | |||
| 21047 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21048 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 21049 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 21050 | tooltipTextField->setVJustify(Field::justify_t::TOP); | |||
| 21051 | tooltipTextField->setColor(makeColor( 188, 154, 114, 255)); | |||
| 21052 | } | |||
| 21053 | if ( auto descFrame = tooltipFrame->addFrame("inventory mouse tooltip description frame") ) | |||
| 21054 | { | |||
| 21055 | descFrame->setHollow(true); | |||
| 21056 | descFrame->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21057 | ||||
| 21058 | descFrame->addImage(SDL_Rect{ 0, 0, 0, 1 }, | |||
| 21059 | makeColor( 49, 53, 61, 255), | |||
| 21060 | "images/system/white.png", "inventory mouse tooltip description divider"); | |||
| 21061 | ||||
| 21062 | tooltipTextField = descFrame->addField("inventory mouse tooltip description", 1024); | |||
| 21063 | tooltipTextField->setText("Nothing"); | |||
| 21064 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21065 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 21066 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 21067 | tooltipTextField->setVJustify(Field::justify_t::TOP); | |||
| 21068 | //tooltipTextField->setColor(makeColor( 188, 154, 114, 255)); | |||
| 21069 | //tooltipTextField->setColor(0xFFFFFFFF); | |||
| 21070 | tooltipTextField->setTextColor(makeColor( 67, 195, 157, 255)); | |||
| 21071 | ||||
| 21072 | tooltipTextField = descFrame->addField("inventory mouse tooltip description positive text", 1024); | |||
| 21073 | tooltipTextField->setText("Nothing"); | |||
| 21074 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21075 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 21076 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 21077 | tooltipTextField->setVJustify(Field::justify_t::TOP); | |||
| 21078 | //tooltipTextField->setColor(makeColor( 1, 151, 246, 255)); | |||
| 21079 | tooltipTextField->setColor(0xFFFFFFFF); | |||
| 21080 | tooltipTextField->setTextColor(makeColor( 188, 154, 114, 255)); | |||
| 21081 | ||||
| 21082 | tooltipTextField = descFrame->addField("inventory mouse tooltip description negative text", 1024); | |||
| 21083 | tooltipTextField->setText("Nothing"); | |||
| 21084 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21085 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 21086 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 21087 | tooltipTextField->setVJustify(Field::justify_t::TOP); | |||
| 21088 | tooltipTextField->setColor(0xFFFFFFFF); | |||
| 21089 | tooltipTextField->setTextColor(makeColor( 215, 38, 61, 255)); | |||
| 21090 | } | |||
| 21091 | if ( auto valueFrame = tooltipFrame->addFrame("inventory mouse tooltip value frame") ) | |||
| 21092 | { | |||
| 21093 | valueFrame->setHollow(true); | |||
| 21094 | valueFrame->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21095 | ||||
| 21096 | valueFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 21097 | makeColor( 49, 53, 61, 255), | |||
| 21098 | "images/system/white.png", "inventory mouse tooltip value background"); | |||
| 21099 | ||||
| 21100 | valueFrame->addImage(SDL_Rect{ 0, 0, 0, 1 }, | |||
| 21101 | makeColor( 49, 53, 61, 255), | |||
| 21102 | "images/system/white.png", "inventory mouse tooltip value divider"); | |||
| 21103 | ||||
| 21104 | tooltipTextField = valueFrame->addField("inventory mouse tooltip identified value", 64); | |||
| 21105 | tooltipTextField->setText("Nothing"); | |||
| 21106 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21107 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 21108 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 21109 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 21110 | tooltipTextField->setColor(makeColor( 188, 154, 114, 255)); | |||
| 21111 | ||||
| 21112 | valueFrame->addImage(SDL_Rect{ 0, 0, 16, 16 }, | |||
| 21113 | 0xFFFFFFFF, | |||
| 21114 | "*#images/ui/Inventory/tooltips/HUD_Tooltip_Icon_Money_00.png", | |||
| 21115 | "inventory mouse tooltip gold image"); | |||
| 21116 | ||||
| 21117 | tooltipTextField = valueFrame->addField("inventory mouse tooltip gold value", 64); | |||
| 21118 | tooltipTextField->setText("Nothing"); | |||
| 21119 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21120 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 21121 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 21122 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 21123 | tooltipTextField->setColor(makeColor( 188, 154, 114, 255)); | |||
| 21124 | ||||
| 21125 | valueFrame->addImage(SDL_Rect{ 0, 0, 16, 16 }, | |||
| 21126 | 0xFFFFFFFF, | |||
| 21127 | "*#images/ui/Inventory/tooltips/HUD_Tooltip_Icon_WGT_00.png", | |||
| 21128 | "inventory mouse tooltip weight image"); | |||
| 21129 | ||||
| 21130 | tooltipTextField = valueFrame->addField("inventory mouse tooltip weight value", 64); | |||
| 21131 | tooltipTextField->setText("Nothing"); | |||
| 21132 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21133 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 21134 | tooltipTextField->setHJustify(Field::justify_t::LEFT); | |||
| 21135 | tooltipTextField->setVJustify(Field::justify_t::CENTER); | |||
| 21136 | tooltipTextField->setColor(makeColor( 188, 154, 114, 255)); | |||
| 21137 | } | |||
| 21138 | if ( auto promptFrame = tooltipFrame->addFrame("inventory mouse tooltip prompt frame") ) | |||
| 21139 | { | |||
| 21140 | promptFrame->setHollow(true); | |||
| 21141 | promptFrame->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21142 | ||||
| 21143 | tooltipTextField = promptFrame->addField("inventory mouse tooltip prompt", 1024); | |||
| 21144 | tooltipTextField->setText("Nothing"); | |||
| 21145 | tooltipTextField->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 21146 | tooltipTextField->setFont(bodyFont.c_str()); | |||
| 21147 | tooltipTextField->setHJustify(Field::justify_t::RIGHT); | |||
| 21148 | tooltipTextField->setVJustify(Field::justify_t::TOP); | |||
| 21149 | tooltipTextField->setColor(makeColor( 148, 82, 3, 255)); | |||
| 21150 | ||||
| 21151 | } | |||
| 21152 | auto tooltipPromptImg = tooltipFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "inventory mouse tooltip prompt img"); | |||
| 21153 | tooltipPromptImg->disabled = true; | |||
| 21154 | ||||
| 21155 | char name[32]; | |||
| 21156 | snprintf(name, sizeof(name), "player interact %d", player); | |||
| 21157 | if ( auto interactFrame = gameUIFrame[player]->addFrame(name) ) | |||
| 21158 | { | |||
| 21159 | players[player]->inventoryUI.interactFrame = interactFrame; | |||
| 21160 | const int interactWidth = 106; | |||
| 21161 | interactFrame->setSize(SDL_Rect{ 0, 0, interactWidth + 6 * 2, 100 }); | |||
| 21162 | interactFrame->setDisabled(true); | |||
| 21163 | interactFrame->setInheritParentFrameOpacity(false); | |||
| 21164 | ||||
| 21165 | Uint32 color = makeColor( 255, 255, 255, 255); | |||
| 21166 | const int topBackgroundHeight = 30; | |||
| 21167 | const int optionHeight = 20; | |||
| 21168 | ||||
| 21169 | interactFrame->addImage(SDL_Rect{ 24, 0, 0, 30 }, | |||
| 21170 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_T03.png", "interact top background"); | |||
| 21171 | interactFrame->addImage(SDL_Rect{ 0, 0, 24, 30 }, | |||
| 21172 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_TL03.png", "interact top left"); | |||
| 21173 | interactFrame->addImage(SDL_Rect{ 0, 0, 24, 30 }, | |||
| 21174 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_TR03.png", "interact top right"); | |||
| 21175 | ||||
| 21176 | interactFrame->addImage(SDL_Rect{ 24, 30, 0, 12 }, | |||
| 21177 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_C03.png", "interact middle background"); | |||
| 21178 | auto ml = interactFrame->addImage(SDL_Rect{ 0, 30, 24, 12 }, | |||
| 21179 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_L03.png", "interact middle left"); | |||
| 21180 | ml->tiled = true; | |||
| 21181 | auto mr = interactFrame->addImage(SDL_Rect{ 0, 30, 24, 12 }, | |||
| 21182 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_R03.png", "interact middle right"); | |||
| 21183 | mr->tiled = true; | |||
| 21184 | ||||
| 21185 | interactFrame->addImage(SDL_Rect{ 24, 96, 0, 14 }, | |||
| 21186 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_B03.png", "interact bottom background"); | |||
| 21187 | interactFrame->addImage(SDL_Rect{ 0, 96, 24, 14 }, | |||
| 21188 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_BL03.png", "interact bottom left"); | |||
| 21189 | interactFrame->addImage(SDL_Rect{ 0, 96, 24, 14 }, | |||
| 21190 | color, "*#images/ui/Inventory/tooltips/HoverItemMenu_BR03.png", "interact bottom right"); | |||
| 21191 | ||||
| 21192 | auto selectmid = interactFrame->addImage(SDL_Rect{ 6, optionHeight - 16, interactWidth, 22 }, | |||
| 21193 | hudColors.itemContextMenuOptionSelectedImg, "*#images/ui/Inventory/tooltips/HoverItemMenu_SelectBack_M03.png", "interact selected highlight mid"); | |||
| 21194 | selectmid->tiled = true; | |||
| 21195 | interactFrame->addImage(SDL_Rect{ 6, optionHeight - 16, 20, 22 }, | |||
| 21196 | hudColors.itemContextMenuOptionSelectedImg, "*#images/ui/Inventory/tooltips/HoverItemMenu_SelectBack_L03.png", "interact selected highlight left"); | |||
| 21197 | interactFrame->addImage(SDL_Rect{ 6, optionHeight - 16, 20, 22 }, | |||
| 21198 | hudColors.itemContextMenuOptionSelectedImg, "*#images/ui/Inventory/tooltips/HoverItemMenu_SelectBack_R03.png", "interact selected highlight right"); | |||
| 21199 | ||||
| 21200 | ||||
| 21201 | const char* interactFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 21202 | ||||
| 21203 | auto interactText = interactFrame->addField("interact text", 32); | |||
| 21204 | interactText->setText(Language::get(4040)); | |||
| 21205 | interactText->setSize(SDL_Rect{ 0, 2, 0, topBackgroundHeight }); | |||
| 21206 | interactText->setFont(interactFont); | |||
| 21207 | interactText->setHJustify(Field::justify_t::CENTER); | |||
| 21208 | interactText->setVJustify(Field::justify_t::CENTER); | |||
| 21209 | interactText->setColor(hudColors.itemContextMenuHeadingText); | |||
| 21210 | ||||
| 21211 | const int interactOptionStartX = 4; | |||
| 21212 | const int interactOptionStartY = 33; | |||
| 21213 | const int glyphSize = 20; | |||
| 21214 | ||||
| 21215 | auto interactGlyph1 = interactFrame->addImage( | |||
| 21216 | SDL_Rect{ interactOptionStartX + 4, interactOptionStartY + 4, glyphSize, glyphSize }, | |||
| 21217 | 0xFFFFFFFF, "", "glyph 1"); | |||
| 21218 | ||||
| 21219 | const int textAlignX = interactGlyph1->pos.x + interactGlyph1->pos.w + 6; | |||
| 21220 | int textAlignY = interactGlyph1->pos.y - 8; | |||
| 21221 | const int textWidth = 80; | |||
| 21222 | const int textHeight = glyphSize + 8; | |||
| 21223 | ||||
| 21224 | Uint32 textColor = hudColors.itemContextMenuOptionText; | |||
| 21225 | ||||
| 21226 | interactText = interactFrame->addField("interact option 1", 32); | |||
| 21227 | interactText->setText(""); | |||
| 21228 | interactText->setSize(SDL_Rect{ | |||
| 21229 | textAlignX, | |||
| 21230 | textAlignY, | |||
| 21231 | textWidth, textHeight }); | |||
| 21232 | interactText->setFont(interactFont); | |||
| 21233 | interactText->setHJustify(Field::justify_t::LEFT); | |||
| 21234 | interactText->setVJustify(Field::justify_t::CENTER); | |||
| 21235 | interactText->setColor(textColor); | |||
| 21236 | ||||
| 21237 | auto interactGlyph2 = interactFrame->addImage( | |||
| 21238 | SDL_Rect{ interactOptionStartX + 4, | |||
| 21239 | interactGlyph1->pos.y + interactGlyph1->pos.h + 4, | |||
| 21240 | glyphSize, glyphSize }, | |||
| 21241 | 0xFFFFFFFF, "", "glyph 2"); | |||
| 21242 | ||||
| 21243 | textAlignY = interactGlyph2->pos.y - 10; | |||
| 21244 | interactText = interactFrame->addField("interact option 2", 32); | |||
| 21245 | interactText->setText(""); | |||
| 21246 | interactText->setSize(SDL_Rect{ | |||
| 21247 | textAlignX, | |||
| 21248 | textAlignY, | |||
| 21249 | textWidth, textHeight }); | |||
| 21250 | interactText->setFont(interactFont); | |||
| 21251 | interactText->setHJustify(Field::justify_t::LEFT); | |||
| 21252 | interactText->setVJustify(Field::justify_t::CENTER); | |||
| 21253 | interactText->setColor(textColor); | |||
| 21254 | ||||
| 21255 | auto interactGlyph3 = interactFrame->addImage( | |||
| 21256 | SDL_Rect{ interactOptionStartX + 4, | |||
| 21257 | interactGlyph2->pos.y + interactGlyph2->pos.h + 4, | |||
| 21258 | glyphSize, glyphSize }, | |||
| 21259 | 0xFFFFFFFF, "", "glyph 3"); | |||
| 21260 | ||||
| 21261 | textAlignY = interactGlyph3->pos.y - 10; | |||
| 21262 | interactText = interactFrame->addField("interact option 3", 32); | |||
| 21263 | interactText->setText(""); | |||
| 21264 | interactText->setSize(SDL_Rect{ | |||
| 21265 | textAlignX, | |||
| 21266 | textAlignY, | |||
| 21267 | textWidth, textHeight }); | |||
| 21268 | interactText->setFont(interactFont); | |||
| 21269 | interactText->setHJustify(Field::justify_t::LEFT); | |||
| 21270 | interactText->setVJustify(Field::justify_t::CENTER); | |||
| 21271 | interactText->setColor(textColor); | |||
| 21272 | ||||
| 21273 | auto interactGlyph4 = interactFrame->addImage( | |||
| 21274 | SDL_Rect{ interactOptionStartX + 4, | |||
| 21275 | interactGlyph3->pos.y + interactGlyph3->pos.h + 4, | |||
| 21276 | glyphSize, glyphSize }, | |||
| 21277 | 0xFFFFFFFF, "", "glyph 4"); | |||
| 21278 | ||||
| 21279 | textAlignY = interactGlyph4->pos.y - 10; | |||
| 21280 | interactText = interactFrame->addField("interact option 4", 32); | |||
| 21281 | interactText->setText(""); | |||
| 21282 | interactText->setSize(SDL_Rect{ | |||
| 21283 | textAlignX, | |||
| 21284 | textAlignY, | |||
| 21285 | textWidth, textHeight }); | |||
| 21286 | interactText->setFont(interactFont); | |||
| 21287 | interactText->setHJustify(Field::justify_t::LEFT); | |||
| 21288 | interactText->setVJustify(Field::justify_t::CENTER); | |||
| 21289 | interactText->setColor(textColor); | |||
| 21290 | ||||
| 21291 | auto interactGlyph5 = interactFrame->addImage( | |||
| 21292 | SDL_Rect{ interactOptionStartX + 4, | |||
| 21293 | interactGlyph4->pos.y + interactGlyph4->pos.h + 4, | |||
| 21294 | glyphSize, glyphSize }, | |||
| 21295 | 0xFFFFFFFF, "", "glyph 5"); | |||
| 21296 | ||||
| 21297 | textAlignY = interactGlyph5->pos.y - 10; | |||
| 21298 | interactText = interactFrame->addField("interact option 5", 32); | |||
| 21299 | interactText->setText(""); | |||
| 21300 | interactText->setSize(SDL_Rect{ | |||
| 21301 | textAlignX, | |||
| 21302 | textAlignY, | |||
| 21303 | textWidth, textHeight }); | |||
| 21304 | interactText->setFont(interactFont); | |||
| 21305 | interactText->setHJustify(Field::justify_t::LEFT); | |||
| 21306 | interactText->setVJustify(Field::justify_t::CENTER); | |||
| 21307 | interactText->setColor(textColor); | |||
| 21308 | } | |||
| 21309 | ||||
| 21310 | snprintf(name, sizeof(name), "player item prompt %d", player); | |||
| 21311 | if ( auto promptFrame = players[player]->inventoryUI.tooltipContainerFrame->addFrame(name) ) | |||
| 21312 | { | |||
| 21313 | players[player]->inventoryUI.tooltipPromptFrame = promptFrame; | |||
| 21314 | const int interactWidth = 0; | |||
| 21315 | SDL_Rect promptSize{ 0, 0, interactWidth + 6 * 2, 100 }; | |||
| 21316 | promptFrame->setDisabled(true); | |||
| 21317 | promptFrame->setInheritParentFrameOpacity(false); | |||
| 21318 | ||||
| 21319 | Uint32 color = makeColor( 255, 255, 255, 192); | |||
| 21320 | ||||
| 21321 | auto middleCenter = promptFrame->addImage(SDL_Rect{ 6, 2, interactWidth, 76 }, | |||
| 21322 | color, "*#images/ui/Inventory/tooltips/Hover_C00.png", "interact middle background"); | |||
| 21323 | auto middleTop = promptFrame->addImage(SDL_Rect{ 6, 0, interactWidth, 2 }, | |||
| 21324 | color, "*#images/ui/Inventory/tooltips/HoverExt_C00.png", "interact middle top background"); | |||
| 21325 | auto middleBottom = promptFrame->addImage(SDL_Rect{ 6, 0, interactWidth, 2 }, | |||
| 21326 | color, "*#images/ui/Inventory/tooltips/HoverExt_C00.png", "interact middle bottom background"); | |||
| 21327 | auto middleLeft = promptFrame->addImage(SDL_Rect{ 0, 0, 6, 76 }, | |||
| 21328 | color, "*#images/ui/Inventory/tooltips/HoverExt_L00.png", "interact middle left"); | |||
| 21329 | auto middleRight = promptFrame->addImage(SDL_Rect{ interactWidth + 6, 0, 6, 76 }, | |||
| 21330 | color, "*#images/ui/Inventory/tooltips/HoverExt_R00.png", "interact middle right"); | |||
| 21331 | ||||
| 21332 | auto bottomCenter = promptFrame->addImage(SDL_Rect{ 4, 76, interactWidth + 4, 4 }, | |||
| 21333 | color, "*#images/ui/Inventory/tooltips/HoverExt_B00.png", "interact bottom background"); | |||
| 21334 | auto bottomLeft = promptFrame->addImage(SDL_Rect{ 0, 76, 4, 4 }, | |||
| 21335 | color, "*#images/ui/Inventory/tooltips/HoverExt_BL00.png", "interact bottom left"); | |||
| 21336 | auto bottomRight = promptFrame->addImage(SDL_Rect{ interactWidth + 4 * 2, 76, 4, 4 }, | |||
| 21337 | color, "*#images/ui/Inventory/tooltips/HoverExt_BR00.png", "interact bottom right"); | |||
| 21338 | ||||
| 21339 | const int interactOptionStartX = 60; | |||
| 21340 | const int interactOptionStartY = 4; | |||
| 21341 | const int glyphSizeH = 24; | |||
| 21342 | const int glyphSizeW = 22; | |||
| 21343 | ||||
| 21344 | auto interactGlyph1 = promptFrame->addImage( | |||
| 21345 | SDL_Rect{ interactOptionStartX, interactOptionStartY, glyphSizeW, glyphSizeH }, | |||
| 21346 | 0xFFFFFFFF, "", "glyph 1"); | |||
| 21347 | ||||
| 21348 | auto interactGlyph2 = promptFrame->addImage( | |||
| 21349 | SDL_Rect{ interactGlyph1->pos.x - (glyphSizeW / 2), | |||
| 21350 | interactGlyph1->pos.y + glyphSizeH, | |||
| 21351 | glyphSizeW, glyphSizeH }, | |||
| 21352 | 0xFFFFFFFF, "", "glyph 2"); | |||
| 21353 | ||||
| 21354 | auto interactGlyph3 = promptFrame->addImage( | |||
| 21355 | SDL_Rect{ interactGlyph1->pos.x + (glyphSizeW + glyphSizeW / 4), interactGlyph1->pos.y, glyphSizeW, glyphSizeH }, | |||
| 21356 | 0xFFFFFFFF, "", "glyph 3"); | |||
| 21357 | ||||
| 21358 | auto interactGlyph4 = promptFrame->addImage( | |||
| 21359 | SDL_Rect{ interactGlyph3->pos.x - (glyphSizeW / 2), interactGlyph2->pos.y, | |||
| 21360 | glyphSizeW, glyphSizeH }, | |||
| 21361 | 0xFFFFFFFF, "", "glyph 4"); | |||
| 21362 | ||||
| 21363 | auto grabIcon = promptFrame->addImage( | |||
| 21364 | SDL_Rect{ 0, 0, 0, 0 }, | |||
| 21365 | 0xFFFFFFFF, "*#images/ui/Inventory/tooltips/Inventory_Grab.png", "grab icon"); | |||
| 21366 | grabIcon->disabled = true; | |||
| 21367 | auto dropIcon = promptFrame->addImage( | |||
| 21368 | SDL_Rect{ 0, 0, 0, 0 }, | |||
| 21369 | 0xFFFFFFFF, "*#images/ui/Inventory/tooltips/Inventory_Drop.png", "drop icon"); | |||
| 21370 | dropIcon->disabled = true; | |||
| 21371 | ||||
| 21372 | const int textWidth = 200; | |||
| 21373 | const int textHeight = glyphSizeH + 8; | |||
| 21374 | ||||
| 21375 | Uint32 promptTextColor = makeColor( 188, 154, 114, 255); | |||
| 21376 | const char * promptFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 21377 | int textAlignY = interactGlyph1->pos.y - 4; | |||
| 21378 | int textAlignXRightJustify = interactGlyph1->pos.x - 6 - textWidth; | |||
| 21379 | auto promptText = promptFrame->addField("txt 1", 32); | |||
| 21380 | promptText->setText(Language::get(4050)); | |||
| 21381 | promptText->setSize(SDL_Rect{ | |||
| 21382 | textAlignXRightJustify, | |||
| 21383 | textAlignY, | |||
| 21384 | textWidth, textHeight }); | |||
| 21385 | promptText->setFont(promptFont); | |||
| 21386 | promptText->setHJustify(Field::justify_t::RIGHT); | |||
| 21387 | promptText->setVJustify(Field::justify_t::CENTER); | |||
| 21388 | promptText->setColor(promptTextColor); | |||
| 21389 | ||||
| 21390 | textAlignXRightJustify = interactGlyph2->pos.x - 6 - textWidth; | |||
| 21391 | textAlignY = interactGlyph2->pos.y - 4; | |||
| 21392 | promptText = promptFrame->addField("txt 2", 32); | |||
| 21393 | promptText->setText(Language::get(4040)); | |||
| 21394 | promptText->setSize(SDL_Rect{ | |||
| 21395 | textAlignXRightJustify, | |||
| 21396 | textAlignY, | |||
| 21397 | textWidth, textHeight }); | |||
| 21398 | promptText->setFont(promptFont); | |||
| 21399 | promptText->setHJustify(Field::justify_t::RIGHT); | |||
| 21400 | promptText->setVJustify(Field::justify_t::CENTER); | |||
| 21401 | promptText->setColor(promptTextColor); | |||
| 21402 | ||||
| 21403 | int textAlignXLeftJustify = interactGlyph3->pos.x + interactGlyph3->pos.w + 6; | |||
| 21404 | textAlignY = interactGlyph3->pos.y - 4; | |||
| 21405 | promptText = promptFrame->addField("txt 3", 32); | |||
| 21406 | promptText->setText(Language::get(5956)); | |||
| 21407 | promptText->setSize(SDL_Rect{ | |||
| 21408 | textAlignXLeftJustify, | |||
| 21409 | textAlignY, | |||
| 21410 | textWidth, textHeight }); | |||
| 21411 | promptText->setFont(promptFont); | |||
| 21412 | promptText->setHJustify(Field::justify_t::LEFT); | |||
| 21413 | promptText->setVJustify(Field::justify_t::CENTER); | |||
| 21414 | promptText->setColor(promptTextColor); | |||
| 21415 | ||||
| 21416 | textAlignXLeftJustify = interactGlyph4->pos.x + interactGlyph4->pos.w + 6; | |||
| 21417 | textAlignY = interactGlyph4->pos.y - 4; | |||
| 21418 | promptText = promptFrame->addField("txt 4", 32); | |||
| 21419 | promptText->setText(Language::get(5957)); | |||
| 21420 | promptText->setSize(SDL_Rect{ | |||
| 21421 | textAlignXLeftJustify, | |||
| 21422 | textAlignY, | |||
| 21423 | textWidth, textHeight }); | |||
| 21424 | promptText->setFont(promptFont); | |||
| 21425 | promptText->setHJustify(Field::justify_t::LEFT); | |||
| 21426 | promptText->setVJustify(Field::justify_t::CENTER); | |||
| 21427 | promptText->setColor(promptTextColor); | |||
| 21428 | ||||
| 21429 | bottomCenter->pos.y = interactGlyph4->pos.y + interactGlyph4->pos.h + 2; | |||
| 21430 | bottomLeft->pos.y = bottomCenter->pos.y; | |||
| 21431 | bottomRight->pos.y = bottomCenter->pos.y; | |||
| 21432 | ||||
| 21433 | promptSize.h = bottomCenter->pos.y + bottomCenter->pos.h; | |||
| 21434 | ||||
| 21435 | promptFrame->setSize(promptSize); | |||
| 21436 | middleCenter->pos.h = bottomCenter->pos.y - 4; | |||
| 21437 | middleLeft->pos.h = bottomCenter->pos.y; | |||
| 21438 | middleRight->pos.h = bottomCenter->pos.y; | |||
| 21439 | middleBottom->pos.y = bottomCenter->pos.y - 2; | |||
| 21440 | } | |||
| 21441 | } | |||
| 21442 | ||||
| 21443 | view_t playerPortraitView[MAXPLAYERS4]; | |||
| 21444 | ||||
| 21445 | void drawCharacterPreview(const int player, SDL_Rect pos, int fov, real_t offsetyaw, bool dark) | |||
| 21446 | { | |||
| 21447 | if (player < 0 || player >= MAXPLAYERS4) { | |||
| 21448 | return; | |||
| 21449 | } | |||
| 21450 | view_t& view = playerPortraitView[player]; | |||
| 21451 | auto ofov = ::fov; | |||
| 21452 | ::fov = fov; | |||
| 21453 | ||||
| 21454 | //TempTexture* minimapTexture = new TempTexture(); | |||
| 21455 | auto playerEntity = Player::getPlayerInteractEntity(player); | |||
| 21456 | ||||
| 21457 | if ( playerEntity ) | |||
| 21458 | { | |||
| 21459 | GL_CHECK_ERR(glClear(GL_DEPTH_BUFFER_BIT))({ glClear(0x00000100); GLenum err; while((err = glGetError() ) != 0) { printlog("[OpenGL]: ERROR type = 0x%x, message = %s" , err, gl_error_string(err)); }}); | |||
| 21460 | ||||
| 21461 | static ConsoleVariable<bool> cvar_char_portrait_static_angle("/char_portrait_static_angle", true); | |||
| 21462 | view.x = playerEntity->x / 16.0 + (.92 * cos(offsetyaw | |||
| 21463 | + (*cvar_char_portrait_static_angle ? playerEntity->yaw : 0))); | |||
| 21464 | view.y = playerEntity->y / 16.0 + (.92 * sin(offsetyaw | |||
| 21465 | + (*cvar_char_portrait_static_angle ? playerEntity->yaw : 0))); | |||
| 21466 | view.z = playerEntity->z * 2; | |||
| 21467 | view.ang = (offsetyaw - PI3.14159265358979323846 | |||
| 21468 | + (*cvar_char_portrait_static_angle ? playerEntity->yaw : 0)); //5 * PI / 4; | |||
| 21469 | view.vang = PI3.14159265358979323846 / 20; | |||
| 21470 | ||||
| 21471 | view.winx = pos.x; | |||
| 21472 | // winy modification required due to new frame scaling method d49b1a5f34667432f2a2bd754c0abca3a09227c8 | |||
| 21473 | view.winy = pos.y + (yres - Frame::virtualScreenY); | |||
| 21474 | //view.winx = x1 + 8; | |||
| 21475 | //view.winy = y1 + 8; | |||
| 21476 | ||||
| 21477 | view.winw = pos.w; | |||
| 21478 | view.winh = pos.h; | |||
| 21479 | glBeginCamera(&view, false); | |||
| 21480 | bool b = playerEntity->flags[BRIGHT1]; | |||
| 21481 | if (!dark) { playerEntity->flags[BRIGHT1] = true; } | |||
| 21482 | if ( !playerEntity->flags[INVISIBLE2] ) | |||
| 21483 | { | |||
| 21484 | glDrawVoxel(&view, playerEntity, REALCOLORS0); | |||
| 21485 | } | |||
| 21486 | playerEntity->flags[BRIGHT1] = b; | |||
| 21487 | int c = 0; | |||
| 21488 | if ( multiplayer != CLIENT2 ) | |||
| 21489 | { | |||
| 21490 | for ( node_t* node = playerEntity->children.first; node != nullptr; node = node->next ) | |||
| 21491 | { | |||
| 21492 | if ( playerEntity->behavior == &actPlayer ) | |||
| 21493 | { | |||
| 21494 | if ( c == 0 ) | |||
| 21495 | { | |||
| 21496 | c++; | |||
| 21497 | continue; | |||
| 21498 | } | |||
| 21499 | } | |||
| 21500 | Entity* entity = (Entity*)node->element; | |||
| 21501 | if ( !entity->flags[INVISIBLE2] ) | |||
| 21502 | { | |||
| 21503 | bool b = entity->flags[BRIGHT1]; | |||
| 21504 | if (!dark) { entity->flags[BRIGHT1] = true; } | |||
| 21505 | glDrawVoxel(&view, entity, REALCOLORS0); | |||
| 21506 | entity->flags[BRIGHT1] = b; | |||
| 21507 | } | |||
| 21508 | c++; | |||
| 21509 | } | |||
| 21510 | for ( node_t* node = map.entities->first; node != NULL__null; node = node->next ) | |||
| 21511 | { | |||
| 21512 | Entity* entity = (Entity*)node->element; | |||
| 21513 | if ( (Sint32)entity->getUID() == -4 ) // torch sprites | |||
| 21514 | { | |||
| 21515 | if ( (entity->skill[1] - 1) != player ) | |||
| 21516 | { | |||
| 21517 | continue; | |||
| 21518 | } | |||
| 21519 | bool b = entity->flags[BRIGHT1]; | |||
| 21520 | if (!dark) { entity->flags[BRIGHT1] = true; } | |||
| 21521 | glDrawSprite(&view, entity, REALCOLORS0); | |||
| 21522 | entity->flags[BRIGHT1] = b; | |||
| 21523 | } | |||
| 21524 | } | |||
| 21525 | } | |||
| 21526 | else | |||
| 21527 | { | |||
| 21528 | for ( node_t* node = map.entities->first; node != NULL__null; node = node->next ) | |||
| 21529 | { | |||
| 21530 | Entity* entity = (Entity*)node->element; | |||
| 21531 | if ( playerEntity->behavior == &actPlayer ) | |||
| 21532 | { | |||
| 21533 | if ( (entity->behavior == &actPlayerLimb && entity->skill[2] == player && !entity->flags[INVISIBLE2]) || (Sint32)entity->getUID() == -4 ) | |||
| 21534 | { | |||
| 21535 | if ( (Sint32)entity->getUID() == -4 ) // torch sprites | |||
| 21536 | { | |||
| 21537 | if ( (entity->skill[1] - 1) != player ) | |||
| 21538 | { | |||
| 21539 | continue; | |||
| 21540 | } | |||
| 21541 | bool b = entity->flags[BRIGHT1]; | |||
| 21542 | if (!dark) { entity->flags[BRIGHT1] = true; } | |||
| 21543 | glDrawSprite(&view, entity, REALCOLORS0); | |||
| 21544 | entity->flags[BRIGHT1] = b; | |||
| 21545 | } | |||
| 21546 | else | |||
| 21547 | { | |||
| 21548 | bool b = entity->flags[BRIGHT1]; | |||
| 21549 | if (!dark) { entity->flags[BRIGHT1] = true; } | |||
| 21550 | glDrawVoxel(&view, entity, REALCOLORS0); | |||
| 21551 | entity->flags[BRIGHT1] = b; | |||
| 21552 | } | |||
| 21553 | } | |||
| 21554 | } | |||
| 21555 | else if ( playerEntity->behavior == &actDeathGhost ) | |||
| 21556 | { | |||
| 21557 | if ( entity->behavior == &actDeathGhostLimb && entity->skill[2] == player && !entity->flags[INVISIBLE2] ) | |||
| 21558 | { | |||
| 21559 | bool b = entity->flags[BRIGHT1]; | |||
| 21560 | if ( !dark ) { entity->flags[BRIGHT1] = true; } | |||
| 21561 | glDrawVoxel(&view, entity, REALCOLORS0); | |||
| 21562 | entity->flags[BRIGHT1] = b; | |||
| 21563 | } | |||
| 21564 | } | |||
| 21565 | } | |||
| 21566 | } | |||
| 21567 | if (drawingGui) { | |||
| 21568 | // blending gets disabled after objects are drawn, so re-enable it. | |||
| 21569 | GL_CHECK_ERR(glEnable(GL_BLEND))({ glEnable(0x0BE2); GLenum err; while((err = glGetError()) != 0) { printlog("[OpenGL]: ERROR type = 0x%x, message = %s", err , gl_error_string(err)); }}); | |||
| 21570 | } | |||
| 21571 | glEndCamera(&view, false); | |||
| 21572 | } | |||
| 21573 | ::fov = ofov; | |||
| 21574 | } | |||
| 21575 | ||||
| 21576 | Player::SkillSheet_t::SkillSheetData_t Player::SkillSheet_t::skillSheetData; | |||
| 21577 | void Player::SkillSheet_t::loadSkillSheetJSON() | |||
| 21578 | { | |||
| 21579 | if ( !PHYSFS_getRealDir("/data/skillsheet_entries.json") ) | |||
| 21580 | { | |||
| 21581 | printlog("[JSON]: Error: Could not find file: data/skillsheet_entries.json"); | |||
| 21582 | } | |||
| 21583 | else | |||
| 21584 | { | |||
| 21585 | std::string inputPath = PHYSFS_getRealDir("/data/skillsheet_entries.json"); | |||
| 21586 | inputPath.append("/data/skillsheet_entries.json"); | |||
| 21587 | ||||
| 21588 | File* fp = FileIO::open(inputPath.c_str(), "rb"); | |||
| 21589 | if ( !fp ) | |||
| 21590 | { | |||
| 21591 | printlog("[JSON]: Error: Could not open json file %s", inputPath.c_str()); | |||
| 21592 | } | |||
| 21593 | else | |||
| 21594 | { | |||
| 21595 | char buf[65536]; | |||
| 21596 | int count = fp->read(buf, sizeof(buf[0]), sizeof(buf)); | |||
| 21597 | buf[count] = '\0'; | |||
| 21598 | rapidjson::StringStream is(buf); | |||
| 21599 | FileIO::close(fp); | |||
| 21600 | rapidjson::Document d; | |||
| 21601 | d.ParseStream(is); | |||
| 21602 | if ( !d.HasMember("version") ) | |||
| 21603 | { | |||
| 21604 | printlog("[JSON]: Error: No 'version' value in json file, or JSON syntax incorrect! %s", inputPath.c_str()); | |||
| 21605 | } | |||
| 21606 | else | |||
| 21607 | { | |||
| 21608 | if ( d.HasMember("skills") ) | |||
| 21609 | { | |||
| 21610 | auto& allEntries = skillSheetData.skillEntries; | |||
| 21611 | allEntries.clear(); | |||
| 21612 | for ( rapidjson::Value::ConstValueIterator itr = d["skills"].Begin(); | |||
| 21613 | itr != d["skills"].End(); ++itr ) | |||
| 21614 | { | |||
| 21615 | allEntries.push_back(SkillSheetData_t::SkillEntry_t()); | |||
| 21616 | auto& entry = allEntries[allEntries.size() - 1]; | |||
| 21617 | if ( (*itr).HasMember("name") ) | |||
| 21618 | { | |||
| 21619 | entry.name = (*itr)["name"].GetString(); | |||
| 21620 | } | |||
| 21621 | if ( (*itr).HasMember("id") ) | |||
| 21622 | { | |||
| 21623 | entry.skillId = (*itr)["id"].GetInt(); | |||
| 21624 | } | |||
| 21625 | if ( (*itr).HasMember("sfx") ) | |||
| 21626 | { | |||
| 21627 | entry.skillSfx = (*itr)["sfx"].GetInt(); | |||
| 21628 | } | |||
| 21629 | if ( (*itr).HasMember("icon_base_path") ) | |||
| 21630 | { | |||
| 21631 | entry.skillIconPath = (*itr)["icon_base_path"].GetString(); | |||
| 21632 | } | |||
| 21633 | if ( (*itr).HasMember("icon_legend_path") ) | |||
| 21634 | { | |||
| 21635 | entry.skillIconPathLegend = (*itr)["icon_legend_path"].GetString(); | |||
| 21636 | } | |||
| 21637 | if ( (*itr).HasMember("icon_base_path_32px") ) | |||
| 21638 | { | |||
| 21639 | entry.skillIconPath32px = (*itr)["icon_base_path_32px"].GetString(); | |||
| 21640 | } | |||
| 21641 | if ( (*itr).HasMember("icon_legend_path_32px") ) | |||
| 21642 | { | |||
| 21643 | entry.skillIconPathLegend32px = (*itr)["icon_legend_path_32px"].GetString(); | |||
| 21644 | } | |||
| 21645 | if ( (*itr).HasMember("icon_stat_path") ) | |||
| 21646 | { | |||
| 21647 | entry.statIconPath = (*itr)["icon_stat_path"].GetString(); | |||
| 21648 | } | |||
| 21649 | if ( (*itr).HasMember("description") ) | |||
| 21650 | { | |||
| 21651 | entry.description = (*itr)["description"].GetString(); | |||
| 21652 | } | |||
| 21653 | if ( (*itr).HasMember("legend_text") ) | |||
| 21654 | { | |||
| 21655 | entry.legendaryDescription = (*itr)["legend_text"].GetString(); | |||
| 21656 | } | |||
| 21657 | if ( (*itr).HasMember("effects") ) | |||
| 21658 | { | |||
| 21659 | for ( rapidjson::Value::ConstValueIterator eff_itr = (*itr)["effects"].Begin(); eff_itr != (*itr)["effects"].End(); ++eff_itr ) | |||
| 21660 | { | |||
| 21661 | entry.effects.push_back(SkillSheetData_t::SkillEntry_t::SkillEffect_t()); | |||
| 21662 | auto& effect = entry.effects[entry.effects.size() - 1]; | |||
| 21663 | effect.tag = (*eff_itr)["tag"].GetString(); | |||
| 21664 | effect.title = (*eff_itr)["title"].GetString(); | |||
| 21665 | effect.rawValue = (*eff_itr)["value"].GetString(); | |||
| 21666 | effect.valueCustomWidthOffset = 0; | |||
| 21667 | if ( (*eff_itr).HasMember("custom_value_width_offset") ) | |||
| 21668 | { | |||
| 21669 | effect.valueCustomWidthOffset = (*eff_itr)["custom_value_width_offset"].GetInt(); | |||
| 21670 | } | |||
| 21671 | if ( (*eff_itr).HasMember("auto_resize_value") ) | |||
| 21672 | { | |||
| 21673 | effect.bAllowAutoResizeValue = (*eff_itr)["auto_resize_value"].GetBool(); | |||
| 21674 | } | |||
| 21675 | else | |||
| 21676 | { | |||
| 21677 | effect.bAllowAutoResizeValue = false; | |||
| 21678 | } | |||
| 21679 | if ( (*eff_itr).HasMember("realtime_update") ) | |||
| 21680 | { | |||
| 21681 | effect.bAllowRealtimeUpdate = (*eff_itr)["realtime_update"].GetBool(); | |||
| 21682 | } | |||
| 21683 | else | |||
| 21684 | { | |||
| 21685 | effect.bAllowRealtimeUpdate = false; | |||
| 21686 | } | |||
| 21687 | } | |||
| 21688 | } | |||
| 21689 | if ( (*itr).HasMember("effects_position") ) | |||
| 21690 | { | |||
| 21691 | for ( rapidjson::Value::ConstMemberIterator effPos_itr = (*itr)["effects_position"].MemberBegin(); | |||
| 21692 | effPos_itr != (*itr)["effects_position"].MemberEnd(); ++effPos_itr ) | |||
| 21693 | { | |||
| 21694 | std::string memberName = effPos_itr->name.GetString(); | |||
| 21695 | if ( memberName == "effect_start_offset_x" ) | |||
| 21696 | { | |||
| 21697 | entry.effectStartOffsetX = effPos_itr->value.GetInt(); | |||
| 21698 | } | |||
| 21699 | else if ( memberName == "effect_background_offset_x" ) | |||
| 21700 | { | |||
| 21701 | entry.effectBackgroundOffsetX = effPos_itr->value.GetInt(); | |||
| 21702 | } | |||
| 21703 | else if ( memberName == "effect_background_width" ) | |||
| 21704 | { | |||
| 21705 | entry.effectBackgroundWidth = effPos_itr->value.GetInt(); | |||
| 21706 | } | |||
| 21707 | } | |||
| 21708 | } | |||
| 21709 | } | |||
| 21710 | } | |||
| 21711 | if ( d.HasMember("window_scaling") ) | |||
| 21712 | { | |||
| 21713 | if ( d["window_scaling"].HasMember("standard_scale_modifier_x") ) | |||
| 21714 | { | |||
| 21715 | windowHeightScaleX = d["window_scaling"]["standard_scale_modifier_x"].GetDouble(); | |||
| 21716 | } | |||
| 21717 | if ( d["window_scaling"].HasMember("standard_scale_modifier_y") ) | |||
| 21718 | { | |||
| 21719 | windowHeightScaleY = d["window_scaling"]["standard_scale_modifier_y"].GetDouble(); | |||
| 21720 | } | |||
| 21721 | if ( d["window_scaling"].HasMember("compact_scale_modifier_x") ) | |||
| 21722 | { | |||
| 21723 | windowCompactHeightScaleX = d["window_scaling"]["compact_scale_modifier_x"].GetDouble(); | |||
| 21724 | } | |||
| 21725 | if ( d["window_scaling"].HasMember("compact_scale_modifier_y") ) | |||
| 21726 | { | |||
| 21727 | windowCompactHeightScaleY = d["window_scaling"]["compact_scale_modifier_y"].GetDouble(); | |||
| 21728 | } | |||
| 21729 | } | |||
| 21730 | if ( d.HasMember("skill_select_images") ) | |||
| 21731 | { | |||
| 21732 | if ( d["skill_select_images"].HasMember("highlight_left") ) | |||
| 21733 | { | |||
| 21734 | skillSheetData.highlightSkillImg = d["skill_select_images"]["highlight_left"].GetString(); | |||
| 21735 | } | |||
| 21736 | if ( d["skill_select_images"].HasMember("selected_left") ) | |||
| 21737 | { | |||
| 21738 | skillSheetData.selectSkillImg = d["skill_select_images"]["selected_left"].GetString(); | |||
| 21739 | } | |||
| 21740 | if ( d["skill_select_images"].HasMember("highlight_right") ) | |||
| 21741 | { | |||
| 21742 | skillSheetData.highlightSkillImg_Right = d["skill_select_images"]["highlight_right"].GetString(); | |||
| 21743 | } | |||
| 21744 | if ( d["skill_select_images"].HasMember("selected_right") ) | |||
| 21745 | { | |||
| 21746 | skillSheetData.selectSkillImg_Right = d["skill_select_images"]["selected_right"].GetString(); | |||
| 21747 | } | |||
| 21748 | } | |||
| 21749 | if ( d.HasMember("skill_background_icons") ) | |||
| 21750 | { | |||
| 21751 | if ( d["skill_background_icons"].HasMember("default") ) | |||
| 21752 | { | |||
| 21753 | skillSheetData.iconBgPathDefault = d["skill_background_icons"]["default"].GetString(); | |||
| 21754 | } | |||
| 21755 | if ( d["skill_background_icons"].HasMember("default_selected") ) | |||
| 21756 | { | |||
| 21757 | skillSheetData.iconBgSelectedPathDefault = d["skill_background_icons"]["default_selected"].GetString(); | |||
| 21758 | } | |||
| 21759 | if ( d["skill_background_icons"].HasMember("novice") ) | |||
| 21760 | { | |||
| 21761 | skillSheetData.iconBgPathNovice = d["skill_background_icons"]["novice"].GetString(); | |||
| 21762 | } | |||
| 21763 | if ( d["skill_background_icons"].HasMember("novice_selected") ) | |||
| 21764 | { | |||
| 21765 | skillSheetData.iconBgSelectedPathNovice = d["skill_background_icons"]["novice_selected"].GetString(); | |||
| 21766 | } | |||
| 21767 | if ( d["skill_background_icons"].HasMember("expert") ) | |||
| 21768 | { | |||
| 21769 | skillSheetData.iconBgPathExpert = d["skill_background_icons"]["expert"].GetString(); | |||
| 21770 | } | |||
| 21771 | if ( d["skill_background_icons"].HasMember("expert_selected") ) | |||
| 21772 | { | |||
| 21773 | skillSheetData.iconBgSelectedPathExpert = d["skill_background_icons"]["expert_selected"].GetString(); | |||
| 21774 | } | |||
| 21775 | if ( d["skill_background_icons"].HasMember("legend") ) | |||
| 21776 | { | |||
| 21777 | skillSheetData.iconBgPathLegend = d["skill_background_icons"]["legend"].GetString(); | |||
| 21778 | } | |||
| 21779 | if ( d["skill_background_icons"].HasMember("legend_selected") ) | |||
| 21780 | { | |||
| 21781 | skillSheetData.iconBgSelectedPathLegend = d["skill_background_icons"]["legend_selected"].GetString(); | |||
| 21782 | } | |||
| 21783 | } | |||
| 21784 | if ( d.HasMember("alchemy_potion_names_to_filter") ) | |||
| 21785 | { | |||
| 21786 | skillSheetData.potionNamesToFilter.clear(); | |||
| 21787 | if ( d["alchemy_potion_names_to_filter"].IsString() ) | |||
| 21788 | { | |||
| 21789 | skillSheetData.potionNamesToFilter.push_back(d["alchemy_potion_names_to_filter"].GetString()); | |||
| 21790 | } | |||
| 21791 | else if ( d["alchemy_potion_names_to_filter"].IsArray() ) | |||
| 21792 | { | |||
| 21793 | for ( rapidjson::Value::ConstValueIterator pot_itr = d["alchemy_potion_names_to_filter"].Begin(); | |||
| 21794 | pot_itr != d["alchemy_potion_names_to_filter"].End(); ++pot_itr ) | |||
| 21795 | { | |||
| 21796 | skillSheetData.potionNamesToFilter.push_back(pot_itr->GetString()); | |||
| 21797 | } | |||
| 21798 | } | |||
| 21799 | } | |||
| 21800 | if ( d.HasMember("colors") ) | |||
| 21801 | { | |||
| 21802 | if ( d["colors"].HasMember("default") ) | |||
| 21803 | { | |||
| 21804 | skillSheetData.defaultTextColor = makeColor( | |||
| 21805 | d["colors"]["default"]["r"].GetInt(), | |||
| 21806 | d["colors"]["default"]["g"].GetInt(), | |||
| 21807 | d["colors"]["default"]["b"].GetInt(), | |||
| 21808 | d["colors"]["default"]["a"].GetInt()); | |||
| 21809 | } | |||
| 21810 | if ( d["colors"].HasMember("novice") ) | |||
| 21811 | { | |||
| 21812 | skillSheetData.noviceTextColor = makeColor( | |||
| 21813 | d["colors"]["novice"]["r"].GetInt(), | |||
| 21814 | d["colors"]["novice"]["g"].GetInt(), | |||
| 21815 | d["colors"]["novice"]["b"].GetInt(), | |||
| 21816 | d["colors"]["novice"]["a"].GetInt()); | |||
| 21817 | } | |||
| 21818 | if ( d["colors"].HasMember("expert") ) | |||
| 21819 | { | |||
| 21820 | skillSheetData.expertTextColor = makeColor( | |||
| 21821 | d["colors"]["expert"]["r"].GetInt(), | |||
| 21822 | d["colors"]["expert"]["g"].GetInt(), | |||
| 21823 | d["colors"]["expert"]["b"].GetInt(), | |||
| 21824 | d["colors"]["expert"]["a"].GetInt()); | |||
| 21825 | } | |||
| 21826 | if ( d["colors"].HasMember("legend") ) | |||
| 21827 | { | |||
| 21828 | skillSheetData.legendTextColor = makeColor( | |||
| 21829 | d["colors"]["legend"]["r"].GetInt(), | |||
| 21830 | d["colors"]["legend"]["g"].GetInt(), | |||
| 21831 | d["colors"]["legend"]["b"].GetInt(), | |||
| 21832 | d["colors"]["legend"]["a"].GetInt()); | |||
| 21833 | } | |||
| 21834 | } | |||
| 21835 | printlog("[JSON]: Successfully read json file %s", inputPath.c_str()); | |||
| 21836 | } | |||
| 21837 | } | |||
| 21838 | } | |||
| 21839 | ||||
| 21840 | if ( !PHYSFS_getRealDir("/data/skillsheet_leadership_entries.json") ) | |||
| 21841 | { | |||
| 21842 | printlog("[JSON]: Error: Could not find file: data/skillsheet_leadership_entries.json"); | |||
| 21843 | } | |||
| 21844 | else | |||
| 21845 | { | |||
| 21846 | std::string inputPath = PHYSFS_getRealDir("/data/skillsheet_leadership_entries.json"); | |||
| 21847 | inputPath.append("/data/skillsheet_leadership_entries.json"); | |||
| 21848 | ||||
| 21849 | File* fp = FileIO::open(inputPath.c_str(), "rb"); | |||
| 21850 | if ( !fp ) | |||
| 21851 | { | |||
| 21852 | printlog("[JSON]: Error: Could not open json file %s", inputPath.c_str()); | |||
| 21853 | } | |||
| 21854 | else | |||
| 21855 | { | |||
| 21856 | char buf[65536]; | |||
| 21857 | int count = fp->read(buf, sizeof(buf[0]), sizeof(buf)); | |||
| 21858 | buf[count] = '\0'; | |||
| 21859 | rapidjson::StringStream is(buf); | |||
| 21860 | FileIO::close(fp); | |||
| 21861 | ||||
| 21862 | rapidjson::Document d; | |||
| 21863 | d.ParseStream(is); | |||
| 21864 | if ( !d.HasMember("version") ) | |||
| 21865 | { | |||
| 21866 | printlog("[JSON]: Error: No 'version' value in json file, or JSON syntax incorrect! %s", inputPath.c_str()); | |||
| 21867 | } | |||
| 21868 | else | |||
| 21869 | { | |||
| 21870 | if ( d.HasMember("leadership_allies_base") ) | |||
| 21871 | { | |||
| 21872 | auto& allyTable = skillSheetData.leadershipAllyTableBase; | |||
| 21873 | allyTable.clear(); | |||
| 21874 | for ( rapidjson::Value::ConstMemberIterator itr = d["leadership_allies_base"].MemberBegin(); | |||
| 21875 | itr != d["leadership_allies_base"].MemberEnd(); ++itr ) | |||
| 21876 | { | |||
| 21877 | std::string monsterName = itr->name.GetString(); | |||
| 21878 | int monsterType = -1; | |||
| 21879 | for ( int i = 0; i < NUMMONSTERS; ++i ) | |||
| 21880 | { | |||
| 21881 | if ( monsterName.compare(monstertypename[i]) == 0 ) | |||
| 21882 | { | |||
| 21883 | monsterType = i; | |||
| 21884 | break; | |||
| 21885 | } | |||
| 21886 | } | |||
| 21887 | if ( monsterType < 0 ) { continue; } | |||
| 21888 | if ( itr->value.IsArray() ) | |||
| 21889 | { | |||
| 21890 | for ( rapidjson::Value::ConstValueIterator ally_itr = itr->value.Begin(); | |||
| 21891 | ally_itr != itr->value.End(); ++ally_itr ) | |||
| 21892 | { | |||
| 21893 | std::string allyName = ally_itr->GetString(); | |||
| 21894 | int allyType = -1; | |||
| 21895 | for ( int i = 0; i < NUMMONSTERS; ++i ) | |||
| 21896 | { | |||
| 21897 | if ( allyName.compare(monstertypename[i]) == 0 ) | |||
| 21898 | { | |||
| 21899 | allyType = i; | |||
| 21900 | break; | |||
| 21901 | } | |||
| 21902 | } | |||
| 21903 | if ( allyType >= 0 ) | |||
| 21904 | { | |||
| 21905 | allyTable[(Monster)monsterType].push_back((Monster)allyType); | |||
| 21906 | } | |||
| 21907 | } | |||
| 21908 | } | |||
| 21909 | } | |||
| 21910 | } | |||
| 21911 | if ( d.HasMember("leadership_allies_legendary") ) | |||
| 21912 | { | |||
| 21913 | auto& allyTable = skillSheetData.leadershipAllyTableLegendary; | |||
| 21914 | allyTable.clear(); | |||
| 21915 | for ( rapidjson::Value::ConstMemberIterator itr = d["leadership_allies_legendary"].MemberBegin(); | |||
| 21916 | itr != d["leadership_allies_legendary"].MemberEnd(); ++itr ) | |||
| 21917 | { | |||
| 21918 | std::string monsterName = itr->name.GetString(); | |||
| 21919 | int monsterType = -1; | |||
| 21920 | for ( int i = 0; i < NUMMONSTERS; ++i ) | |||
| 21921 | { | |||
| 21922 | if ( monsterName.compare(monstertypename[i]) == 0 ) | |||
| 21923 | { | |||
| 21924 | monsterType = i; | |||
| 21925 | break; | |||
| 21926 | } | |||
| 21927 | } | |||
| 21928 | if ( monsterType < 0 ) { continue; } | |||
| 21929 | if ( itr->value.IsArray() ) | |||
| 21930 | { | |||
| 21931 | for ( rapidjson::Value::ConstValueIterator ally_itr = itr->value.Begin(); | |||
| 21932 | ally_itr != itr->value.End(); ++ally_itr ) | |||
| 21933 | { | |||
| 21934 | std::string allyName = ally_itr->GetString(); | |||
| 21935 | int allyType = -1; | |||
| 21936 | for ( int i = 0; i < NUMMONSTERS; ++i ) | |||
| 21937 | { | |||
| 21938 | if ( allyName.compare(monstertypename[i]) == 0 ) | |||
| 21939 | { | |||
| 21940 | allyType = i; | |||
| 21941 | break; | |||
| 21942 | } | |||
| 21943 | } | |||
| 21944 | if ( allyType >= 0 ) | |||
| 21945 | { | |||
| 21946 | allyTable[(Monster)monsterType].push_back((Monster)allyType); | |||
| 21947 | } | |||
| 21948 | } | |||
| 21949 | } | |||
| 21950 | } | |||
| 21951 | } | |||
| 21952 | if ( d.HasMember("leadership_allies_unique_recruits") ) | |||
| 21953 | { | |||
| 21954 | auto& allyTable = skillSheetData.leadershipAllyTableSpecialRecruitment; | |||
| 21955 | allyTable.clear(); | |||
| 21956 | for ( rapidjson::Value::ConstMemberIterator itr = d["leadership_allies_unique_recruits"].MemberBegin(); | |||
| 21957 | itr != d["leadership_allies_unique_recruits"].MemberEnd(); ++itr ) | |||
| 21958 | { | |||
| 21959 | std::string monsterName = itr->name.GetString(); | |||
| 21960 | int monsterType = -1; | |||
| 21961 | for ( int i = 0; i < NUMMONSTERS; ++i ) | |||
| 21962 | { | |||
| 21963 | if ( monsterName.compare(monstertypename[i]) == 0 ) | |||
| 21964 | { | |||
| 21965 | monsterType = i; | |||
| 21966 | break; | |||
| 21967 | } | |||
| 21968 | } | |||
| 21969 | if ( monsterType < 0 ) { continue; } | |||
| 21970 | if ( itr->value.IsArray() ) | |||
| 21971 | { | |||
| 21972 | for ( rapidjson::Value::ConstValueIterator ally_itr = itr->value.Begin(); | |||
| 21973 | ally_itr != itr->value.End(); ++ally_itr ) | |||
| 21974 | { | |||
| 21975 | for ( rapidjson::Value::ConstMemberIterator entry_itr = ally_itr->MemberBegin(); | |||
| 21976 | entry_itr != ally_itr->MemberEnd(); ++entry_itr ) | |||
| 21977 | { | |||
| 21978 | std::string allyName = entry_itr->name.GetString(); | |||
| 21979 | int allyType = -1; | |||
| 21980 | for ( int i = 0; i < NUMMONSTERS; ++i ) | |||
| 21981 | { | |||
| 21982 | if ( allyName.compare(monstertypename[i]) == 0 ) | |||
| 21983 | { | |||
| 21984 | allyType = i; | |||
| 21985 | break; | |||
| 21986 | } | |||
| 21987 | } | |||
| 21988 | if ( allyType >= 0 ) | |||
| 21989 | { | |||
| 21990 | allyTable[(Monster)monsterType].push_back(std::make_pair((Monster)allyType, entry_itr->value.GetString())); | |||
| 21991 | } | |||
| 21992 | } | |||
| 21993 | } | |||
| 21994 | } | |||
| 21995 | } | |||
| 21996 | } | |||
| 21997 | printlog("[JSON]: Successfully read json file %s", inputPath.c_str()); | |||
| 21998 | } | |||
| 21999 | } | |||
| 22000 | } | |||
| 22001 | } | |||
| 22002 | ||||
| 22003 | void loadHUDSettingsJSON() | |||
| 22004 | { | |||
| 22005 | if ( !PHYSFS_getRealDir("/data/HUD_settings.json") ) | |||
| 22006 | { | |||
| 22007 | printlog("[JSON]: Error: Could not find file: data/HUD_settings.json"); | |||
| 22008 | } | |||
| 22009 | else | |||
| 22010 | { | |||
| 22011 | std::string inputPath = PHYSFS_getRealDir("/data/HUD_settings.json"); | |||
| 22012 | inputPath.append("/data/HUD_settings.json"); | |||
| 22013 | ||||
| 22014 | File* fp = FileIO::open(inputPath.c_str(), "rb"); | |||
| 22015 | if ( !fp ) | |||
| 22016 | { | |||
| 22017 | printlog("[JSON]: Error: Could not open json file %s", inputPath.c_str()); | |||
| 22018 | } | |||
| 22019 | else | |||
| 22020 | { | |||
| 22021 | char buf[65536]; | |||
| 22022 | int count = fp->read(buf, sizeof(buf[0]), sizeof(buf)); | |||
| 22023 | buf[count] = '\0'; | |||
| 22024 | rapidjson::StringStream is(buf); | |||
| 22025 | FileIO::close(fp); | |||
| 22026 | ||||
| 22027 | rapidjson::Document d; | |||
| 22028 | d.ParseStream(is); | |||
| 22029 | if ( !d.HasMember("version") ) | |||
| 22030 | { | |||
| 22031 | printlog("[JSON]: Error: No 'version' value in json file, or JSON syntax incorrect! %s", inputPath.c_str()); | |||
| 22032 | } | |||
| 22033 | else | |||
| 22034 | { | |||
| 22035 | if ( d.HasMember("selected_cursor_opacity") ) | |||
| 22036 | { | |||
| 22037 | selectedCursorOpacity = d["selected_cursor_opacity"].GetInt(); | |||
| 22038 | } | |||
| 22039 | if ( d.HasMember("selected_old_cursor_opacity") ) | |||
| 22040 | { | |||
| 22041 | oldSelectedCursorOpacity = d["selected_old_cursor_opacity"].GetInt(); | |||
| 22042 | } | |||
| 22043 | if ( d.HasMember("hotbar") ) | |||
| 22044 | { | |||
| 22045 | if ( d["hotbar"].HasMember("hotbar_slot_opacity") ) | |||
| 22046 | { | |||
| 22047 | hotbarSlotOpacity = d["hotbar"]["hotbar_slot_opacity"].GetInt(); | |||
| 22048 | } | |||
| 22049 | if ( d["hotbar"].HasMember("hotbar_selected_slot_opacity") ) | |||
| 22050 | { | |||
| 22051 | hotbarSelectedSlotOpacity = d["hotbar"]["hotbar_selected_slot_opacity"].GetInt(); | |||
| 22052 | } | |||
| 22053 | if ( d["hotbar"].HasMember("hotbar_compact_x_offset") ) | |||
| 22054 | { | |||
| 22055 | hotbarCompactOffsetX = d["hotbar"]["hotbar_compact_x_offset"].GetInt(); | |||
| 22056 | } | |||
| 22057 | if ( d["hotbar"].HasMember("hotbar_compact_slot_overlap") ) | |||
| 22058 | { | |||
| 22059 | hotbarCompactSlotOverlapPercent = d["hotbar"]["hotbar_compact_slot_overlap"].GetDouble(); | |||
| 22060 | } | |||
| 22061 | if ( d["hotbar"].HasMember("hotbar_compact_inactive_slot_movement_x") ) | |||
| 22062 | { | |||
| 22063 | hotbarCompactInactiveSlotMovementX = d["hotbar"]["hotbar_compact_inactive_slot_movement_x"].GetInt(); | |||
| 22064 | } | |||
| 22065 | if ( d["hotbar"].HasMember("hotbar_compact_expanded_x_offset") ) | |||
| 22066 | { | |||
| 22067 | hotbarCompactExpandedOffsetX = d["hotbar"]["hotbar_compact_expanded_x_offset"].GetInt(); | |||
| 22068 | } | |||
| 22069 | if ( d["hotbar"].HasMember("hotbar_y_offset") ) | |||
| 22070 | { | |||
| 22071 | hotbarOffsetY = d["hotbar"]["hotbar_y_offset"].GetInt(); | |||
| 22072 | } | |||
| 22073 | if ( d["hotbar"].HasMember("hotbar_compact_y_offset") ) | |||
| 22074 | { | |||
| 22075 | hotbarCompactOffsetY = d["hotbar"]["hotbar_compact_y_offset"].GetInt(); | |||
| 22076 | } | |||
| 22077 | } | |||
| 22078 | if ( d.HasMember("xpbar") ) | |||
| 22079 | { | |||
| 22080 | if ( d["xpbar"].HasMember("xpbar_width_offset") ) | |||
| 22081 | { | |||
| 22082 | xpbarOffsetWidth = d["xpbar"]["xpbar_width_offset"].GetInt(); | |||
| 22083 | } | |||
| 22084 | if ( d["xpbar"].HasMember("xpbar_compact_width_offset") ) | |||
| 22085 | { | |||
| 22086 | xpbarCompactOffsetWidth = d["xpbar"]["xpbar_compact_width_offset"].GetInt(); | |||
| 22087 | } | |||
| 22088 | if ( d["xpbar"].HasMember("xpbar_y_offset") ) | |||
| 22089 | { | |||
| 22090 | xpbarOffsetY = d["xpbar"]["xpbar_y_offset"].GetInt(); | |||
| 22091 | } | |||
| 22092 | if ( d["xpbar"].HasMember("xpbar_compact_y_offset") ) | |||
| 22093 | { | |||
| 22094 | xpbarCompactOffsetY = d["xpbar"]["xpbar_compact_y_offset"].GetInt(); | |||
| 22095 | } | |||
| 22096 | } | |||
| 22097 | if ( d.HasMember("hpmpbar") ) | |||
| 22098 | { | |||
| 22099 | if ( d["hpmpbar"].HasMember("hpmpbar_width_offset") ) | |||
| 22100 | { | |||
| 22101 | hpmpbarOffsetWidth = d["hpmpbar"]["hpmpbar_width_offset"].GetInt(); | |||
| 22102 | } | |||
| 22103 | if ( d["hpmpbar"].HasMember("hpmpbar_x_offset") ) | |||
| 22104 | { | |||
| 22105 | hpmpbarOffsetX = d["hpmpbar"]["hpmpbar_x_offset"].GetInt(); | |||
| 22106 | } | |||
| 22107 | if ( d["hpmpbar"].HasMember("hpmpbar_y_offset") ) | |||
| 22108 | { | |||
| 22109 | hpmpbarOffsetY = d["hpmpbar"]["hpmpbar_y_offset"].GetInt(); | |||
| 22110 | } | |||
| 22111 | if ( d["hpmpbar"].HasMember("hpmpbar_compact_width_offset") ) | |||
| 22112 | { | |||
| 22113 | hpmpbarCompactOffsetWidth = d["hpmpbar"]["hpmpbar_compact_width_offset"].GetInt(); | |||
| 22114 | } | |||
| 22115 | if ( d["hpmpbar"].HasMember("hpmpbar_compact_x_offset") ) | |||
| 22116 | { | |||
| 22117 | hpmpbarCompactOffsetX = d["hpmpbar"]["hpmpbar_compact_x_offset"].GetInt(); | |||
| 22118 | } | |||
| 22119 | if ( d["hpmpbar"].HasMember("hpmpbar_compact_y_offset") ) | |||
| 22120 | { | |||
| 22121 | hpmpbarCompactOffsetY = d["hpmpbar"]["hpmpbar_compact_y_offset"].GetInt(); | |||
| 22122 | } | |||
| 22123 | ||||
| 22124 | if ( d["hpmpbar"].HasMember("hpmpbar_max_amount_threshold") ) | |||
| 22125 | { | |||
| 22126 | hpmpbarMaxWidthAmount = d["hpmpbar"]["hpmpbar_max_amount_threshold"].GetInt(); | |||
| 22127 | } | |||
| 22128 | if ( d["hpmpbar"].HasMember("hpmpbar_interval_to_increase_width") ) | |||
| 22129 | { | |||
| 22130 | hpmpbarIntervalToIncreaseWidth | |||
| 22131 | = d["hpmpbar"]["hpmpbar_interval_to_increase_width"].GetInt(); | |||
| 22132 | } | |||
| 22133 | if ( d["hpmpbar"].HasMember("hpmpbar_base_percent") ) | |||
| 22134 | { | |||
| 22135 | hpmpbarBasePercentSize = d["hpmpbar"]["hpmpbar_base_percent"].GetInt(); | |||
| 22136 | } | |||
| 22137 | if ( d["hpmpbar"].HasMember("hpmpbar_interval_start_value") ) | |||
| 22138 | { | |||
| 22139 | hpmpbarIntervalStartValue = d["hpmpbar"]["hpmpbar_interval_start_value"].GetInt(); | |||
| 22140 | } | |||
| 22141 | if ( d["hpmpbar"].HasMember("hpmpbar_width_increase_percent_on_interval") ) | |||
| 22142 | { | |||
| 22143 | hpmpbarWidthIncreasePercentOnInterval = | |||
| 22144 | d["hpmpbar"]["hpmpbar_width_increase_percent_on_interval"].GetDouble(); | |||
| 22145 | } | |||
| 22146 | ||||
| 22147 | if ( d["hpmpbar"].HasMember("hpmpbar_compact_max_amount_threshold") ) | |||
| 22148 | { | |||
| 22149 | hpmpbarCompactMaxWidthAmount = d["hpmpbar"]["hpmpbar_compact_max_amount_threshold"].GetInt(); | |||
| 22150 | } | |||
| 22151 | if ( d["hpmpbar"].HasMember("hpmpbar_compact_interval_to_increase_width") ) | |||
| 22152 | { | |||
| 22153 | hpmpbarCompactIntervalToIncreaseWidth = | |||
| 22154 | d["hpmpbar"]["hpmpbar_compact_interval_to_increase_width"].GetInt(); | |||
| 22155 | } | |||
| 22156 | if ( d["hpmpbar"].HasMember("hpmpbar_compact_base_percent") ) | |||
| 22157 | { | |||
| 22158 | hpmpbarCompactBasePercentSize = d["hpmpbar"]["hpmpbar_compact_base_percent"].GetInt(); | |||
| 22159 | } | |||
| 22160 | if ( d["hpmpbar"].HasMember("hpmpbar_compact_interval_start_value") ) | |||
| 22161 | { | |||
| 22162 | hpmpbarCompactIntervalStartValue = d["hpmpbar"]["hpmpbar_compact_interval_start_value"].GetInt(); | |||
| 22163 | } | |||
| 22164 | if ( d["hpmpbar"].HasMember("hpmpbar_compact_width_increase_percent_on_interval") ) | |||
| 22165 | { | |||
| 22166 | hpmpbarCompactWidthIncreasePercentOnInterval = | |||
| 22167 | d["hpmpbar"]["hpmpbar_compact_width_increase_percent_on_interval"].GetDouble(); | |||
| 22168 | } | |||
| 22169 | } | |||
| 22170 | if ( d.HasMember("allybars") ) | |||
| 22171 | { | |||
| 22172 | for ( auto ally_itr = d["allybars"].MemberBegin(); ally_itr != d["allybars"].MemberEnd(); ++ally_itr ) | |||
| 22173 | { | |||
| 22174 | std::string type = ally_itr->name.GetString(); | |||
| 22175 | if ( type == "followers" ) | |||
| 22176 | { | |||
| 22177 | if ( ally_itr->value.HasMember("entry_height") ) | |||
| 22178 | { | |||
| 22179 | AllyStatusBarSettings_t::FollowerBars_t::entrySettings.entryHeight = ally_itr->value["entry_height"].GetInt(); | |||
| 22180 | } | |||
| 22181 | if ( ally_itr->value.HasMember("entry_compact_height") ) | |||
| 22182 | { | |||
| 22183 | AllyStatusBarSettings_t::FollowerBars_t::entrySettings.entryCompactHeight = ally_itr->value["entry_compact_height"].GetInt(); | |||
| 22184 | } | |||
| 22185 | if ( ally_itr->value.HasMember("infinite_scroll") ) | |||
| 22186 | { | |||
| 22187 | Player::HUD_t::FollowerDisplay_t::infiniteScrolling = ally_itr->value["infinite_scroll"].GetBool(); | |||
| 22188 | } | |||
| 22189 | if ( ally_itr->value.HasMember("max_finite_bars") ) | |||
| 22190 | { | |||
| 22191 | Player::HUD_t::FollowerDisplay_t::numFiniteBars = ally_itr->value["max_finite_bars"].GetInt(); | |||
| 22192 | } | |||
| 22193 | if ( ally_itr->value.HasMember("max_fullsize_bars") ) | |||
| 22194 | { | |||
| 22195 | Player::HUD_t::FollowerDisplay_t::numInfiniteFullsizeBars = ally_itr->value["max_fullsize_bars"].GetInt(); | |||
| 22196 | } | |||
| 22197 | if ( ally_itr->value.HasMember("max_compact_bars") ) | |||
| 22198 | { | |||
| 22199 | Player::HUD_t::FollowerDisplay_t::numInfiniteCompactBars = ally_itr->value["max_compact_bars"].GetInt(); | |||
| 22200 | } | |||
| 22201 | if ( ally_itr->value.HasMember("splitscreen_max_fullsize_bars") ) | |||
| 22202 | { | |||
| 22203 | Player::HUD_t::FollowerDisplay_t::numInfiniteSplitscreenFullsizeBars = ally_itr->value["splitscreen_max_fullsize_bars"].GetInt(); | |||
| 22204 | } | |||
| 22205 | if ( ally_itr->value.HasMember("splitscreen_max_compact_bars") ) | |||
| 22206 | { | |||
| 22207 | Player::HUD_t::FollowerDisplay_t::numInfiniteSplitscreenCompactBars = ally_itr->value["splitscreen_max_compact_bars"].GetInt(); | |||
| 22208 | } | |||
| 22209 | if ( ally_itr->value.HasMember("max_fullsize_name_len") ) | |||
| 22210 | { | |||
| 22211 | AllyStatusBarSettings_t::FollowerBars_t::entrySettings.maxNameLengthFullsize = ally_itr->value["max_fullsize_name_len"].GetInt(); | |||
| 22212 | } | |||
| 22213 | if ( ally_itr->value.HasMember("max_compact_name_len") ) | |||
| 22214 | { | |||
| 22215 | AllyStatusBarSettings_t::FollowerBars_t::entrySettings.maxNameLengthCompact = ally_itr->value["max_compact_name_len"].GetInt(); | |||
| 22216 | } | |||
| 22217 | if ( ally_itr->value.HasMember("max_splitscreen_fullsize_name_len") ) | |||
| 22218 | { | |||
| 22219 | AllyStatusBarSettings_t::FollowerBars_t::entrySettings.maxNameLengthSplitscreenFullsize = ally_itr->value["max_splitscreen_fullsize_name_len"].GetInt(); | |||
| 22220 | } | |||
| 22221 | if ( ally_itr->value.HasMember("max_splitscreen_compact_name_len") ) | |||
| 22222 | { | |||
| 22223 | AllyStatusBarSettings_t::FollowerBars_t::entrySettings.maxNameLengthSplitscreenCompact = ally_itr->value["max_splitscreen_compact_name_len"].GetInt(); | |||
| 22224 | } | |||
| 22225 | if ( ally_itr->value.HasMember("base_y_pos") ) | |||
| 22226 | { | |||
| 22227 | AllyStatusBarSettings_t::FollowerBars_t::entrySettings.baseY = ally_itr->value["base_y_pos"].GetInt(); | |||
| 22228 | } | |||
| 22229 | if ( ally_itr->value.HasMember("base_y_pos_splitscreen") ) | |||
| 22230 | { | |||
| 22231 | AllyStatusBarSettings_t::FollowerBars_t::entrySettings.baseYSplitscreen = ally_itr->value["base_y_pos_splitscreen"].GetInt(); | |||
| 22232 | } | |||
| 22233 | if ( ally_itr->value.HasMember("hp") ) | |||
| 22234 | { | |||
| 22235 | for ( auto val_itr = ally_itr->value["hp"].MemberBegin(); | |||
| 22236 | val_itr != ally_itr->value["hp"].MemberEnd(); ++val_itr ) | |||
| 22237 | { | |||
| 22238 | std::string key = val_itr->name.GetString(); | |||
| 22239 | auto& bar = AllyStatusBarSettings_t::FollowerBars_t::hpBar; | |||
| 22240 | if ( key == "bar_pixel_width" ) | |||
| 22241 | { | |||
| 22242 | bar.barPixelWidth = val_itr->value.GetInt(); | |||
| 22243 | } | |||
| 22244 | else if ( key == "bar_compact_pixel_width" ) | |||
| 22245 | { | |||
| 22246 | bar.barCompactPixelWidth = val_itr->value.GetInt(); | |||
| 22247 | } | |||
| 22248 | else if ( key == "bar_splitscreen_pixel_width_offset" ) | |||
| 22249 | { | |||
| 22250 | bar.barSplitscreenPixelWidthOffset = val_itr->value.GetInt(); | |||
| 22251 | } | |||
| 22252 | else if ( key == "bar_max_amount_threshold" ) | |||
| 22253 | { | |||
| 22254 | bar.barMaxWidthAmount = val_itr->value.GetInt(); | |||
| 22255 | } | |||
| 22256 | else if ( key == "bar_interval_to_increase_width" ) | |||
| 22257 | { | |||
| 22258 | bar.barIntervalToIncreaseWidth = val_itr->value.GetInt(); | |||
| 22259 | } | |||
| 22260 | else if ( key == "bar_interval_start_value" ) | |||
| 22261 | { | |||
| 22262 | bar.barIntervalStartValue = val_itr->value.GetInt(); | |||
| 22263 | } | |||
| 22264 | else if ( key == "bar_width_increase_percent_on_interval" ) | |||
| 22265 | { | |||
| 22266 | bar.barWidthIncreasePercentOnInterval = val_itr->value.GetDouble(); | |||
| 22267 | } | |||
| 22268 | else if ( key == "bar_base_percent" ) | |||
| 22269 | { | |||
| 22270 | bar.barBasePercentSize = val_itr->value.GetInt(); | |||
| 22271 | } | |||
| 22272 | else if ( key == "bar_compact_max_amount_threshold" ) | |||
| 22273 | { | |||
| 22274 | bar.barCompactMaxWidthAmount = val_itr->value.GetInt(); | |||
| 22275 | } | |||
| 22276 | else if ( key == "bar_compact_interval_to_increase_width" ) | |||
| 22277 | { | |||
| 22278 | bar.barCompactIntervalToIncreaseWidth = val_itr->value.GetInt(); | |||
| 22279 | } | |||
| 22280 | else if ( key == "bar_compact_interval_start_value" ) | |||
| 22281 | { | |||
| 22282 | bar.barCompactIntervalStartValue = val_itr->value.GetInt(); | |||
| 22283 | } | |||
| 22284 | else if ( key == "bar_compact_width_increase_percent_on_interval" ) | |||
| 22285 | { | |||
| 22286 | bar.barCompactWidthIncreasePercentOnInterval = val_itr->value.GetDouble(); | |||
| 22287 | } | |||
| 22288 | else if ( key == "bar_compact_base_percent" ) | |||
| 22289 | { | |||
| 22290 | bar.barCompactBasePercentSize = val_itr->value.GetInt(); | |||
| 22291 | } | |||
| 22292 | } | |||
| 22293 | } | |||
| 22294 | if ( ally_itr->value.HasMember("mp") ) | |||
| 22295 | { | |||
| 22296 | for ( auto val_itr = ally_itr->value["mp"].MemberBegin(); | |||
| 22297 | val_itr != ally_itr->value["mp"].MemberEnd(); ++val_itr ) | |||
| 22298 | { | |||
| 22299 | std::string key = val_itr->name.GetString(); | |||
| 22300 | auto& bar = AllyStatusBarSettings_t::FollowerBars_t::mpBar; | |||
| 22301 | if ( key == "bar_pixel_width" ) | |||
| 22302 | { | |||
| 22303 | bar.barPixelWidth = val_itr->value.GetInt(); | |||
| 22304 | } | |||
| 22305 | else if ( key == "bar_compact_pixel_width" ) | |||
| 22306 | { | |||
| 22307 | bar.barCompactPixelWidth = val_itr->value.GetInt(); | |||
| 22308 | } | |||
| 22309 | else if ( key == "bar_max_amount_threshold" ) | |||
| 22310 | { | |||
| 22311 | bar.barMaxWidthAmount = val_itr->value.GetInt(); | |||
| 22312 | } | |||
| 22313 | else if ( key == "bar_interval_to_increase_width" ) | |||
| 22314 | { | |||
| 22315 | bar.barIntervalToIncreaseWidth = val_itr->value.GetInt(); | |||
| 22316 | } | |||
| 22317 | else if ( key == "bar_interval_start_value" ) | |||
| 22318 | { | |||
| 22319 | bar.barIntervalStartValue = val_itr->value.GetInt(); | |||
| 22320 | } | |||
| 22321 | else if ( key == "bar_width_increase_percent_on_interval" ) | |||
| 22322 | { | |||
| 22323 | bar.barWidthIncreasePercentOnInterval = val_itr->value.GetDouble(); | |||
| 22324 | } | |||
| 22325 | else if ( key == "bar_base_percent" ) | |||
| 22326 | { | |||
| 22327 | bar.barBasePercentSize = val_itr->value.GetInt(); | |||
| 22328 | } | |||
| 22329 | else if ( key == "bar_compact_max_amount_threshold" ) | |||
| 22330 | { | |||
| 22331 | bar.barCompactMaxWidthAmount = val_itr->value.GetInt(); | |||
| 22332 | } | |||
| 22333 | else if ( key == "bar_compact_interval_to_increase_width" ) | |||
| 22334 | { | |||
| 22335 | bar.barCompactIntervalToIncreaseWidth = val_itr->value.GetInt(); | |||
| 22336 | } | |||
| 22337 | else if ( key == "bar_compact_interval_start_value" ) | |||
| 22338 | { | |||
| 22339 | bar.barCompactIntervalStartValue = val_itr->value.GetInt(); | |||
| 22340 | } | |||
| 22341 | else if ( key == "bar_compact_width_increase_percent_on_interval" ) | |||
| 22342 | { | |||
| 22343 | bar.barCompactWidthIncreasePercentOnInterval = val_itr->value.GetDouble(); | |||
| 22344 | } | |||
| 22345 | else if ( key == "bar_compact_base_percent" ) | |||
| 22346 | { | |||
| 22347 | bar.barCompactBasePercentSize = val_itr->value.GetInt(); | |||
| 22348 | } | |||
| 22349 | } | |||
| 22350 | } | |||
| 22351 | } | |||
| 22352 | else if ( type == "players" ) | |||
| 22353 | { | |||
| 22354 | if ( ally_itr->value.HasMember("entry_height") ) | |||
| 22355 | { | |||
| 22356 | AllyStatusBarSettings_t::PlayerBars_t::entrySettings.entryHeight = ally_itr->value["entry_height"].GetInt(); | |||
| 22357 | } | |||
| 22358 | if ( ally_itr->value.HasMember("entry_compact_height") ) | |||
| 22359 | { | |||
| 22360 | AllyStatusBarSettings_t::PlayerBars_t::entrySettings.entryCompactHeight = ally_itr->value["entry_compact_height"].GetInt(); | |||
| 22361 | } | |||
| 22362 | if ( ally_itr->value.HasMember("max_fullsize_name_len") ) | |||
| 22363 | { | |||
| 22364 | AllyStatusBarSettings_t::PlayerBars_t::entrySettings.maxNameLengthFullsize = ally_itr->value["max_fullsize_name_len"].GetInt(); | |||
| 22365 | } | |||
| 22366 | if ( ally_itr->value.HasMember("max_compact_name_len") ) | |||
| 22367 | { | |||
| 22368 | AllyStatusBarSettings_t::PlayerBars_t::entrySettings.maxNameLengthCompact = ally_itr->value["max_compact_name_len"].GetInt(); | |||
| 22369 | } | |||
| 22370 | if ( ally_itr->value.HasMember("max_splitscreen_fullsize_name_len") ) | |||
| 22371 | { | |||
| 22372 | AllyStatusBarSettings_t::PlayerBars_t::entrySettings.maxNameLengthSplitscreenFullsize = ally_itr->value["max_splitscreen_fullsize_name_len"].GetInt(); | |||
| 22373 | } | |||
| 22374 | if ( ally_itr->value.HasMember("max_splitscreen_compact_name_len") ) | |||
| 22375 | { | |||
| 22376 | AllyStatusBarSettings_t::PlayerBars_t::entrySettings.maxNameLengthSplitscreenCompact = ally_itr->value["max_splitscreen_compact_name_len"].GetInt(); | |||
| 22377 | } | |||
| 22378 | if ( ally_itr->value.HasMember("base_y_pos") ) | |||
| 22379 | { | |||
| 22380 | AllyStatusBarSettings_t::PlayerBars_t::entrySettings.baseY = ally_itr->value["base_y_pos"].GetInt(); | |||
| 22381 | } | |||
| 22382 | if ( ally_itr->value.HasMember("base_y_pos_splitscreen") ) | |||
| 22383 | { | |||
| 22384 | AllyStatusBarSettings_t::PlayerBars_t::entrySettings.baseYSplitscreen = ally_itr->value["base_y_pos_splitscreen"].GetInt(); | |||
| 22385 | } | |||
| 22386 | if ( ally_itr->value.HasMember("hp") ) | |||
| 22387 | { | |||
| 22388 | for ( auto val_itr = ally_itr->value["hp"].MemberBegin(); | |||
| 22389 | val_itr != ally_itr->value["hp"].MemberEnd(); ++val_itr ) | |||
| 22390 | { | |||
| 22391 | std::string key = val_itr->name.GetString(); | |||
| 22392 | auto& bar = AllyStatusBarSettings_t::PlayerBars_t::hpBar; | |||
| 22393 | if ( key == "bar_pixel_width" ) | |||
| 22394 | { | |||
| 22395 | bar.barPixelWidth = val_itr->value.GetInt(); | |||
| 22396 | } | |||
| 22397 | else if ( key == "bar_compact_pixel_width" ) | |||
| 22398 | { | |||
| 22399 | bar.barCompactPixelWidth = val_itr->value.GetInt(); | |||
| 22400 | } | |||
| 22401 | else if ( key == "bar_max_amount_threshold" ) | |||
| 22402 | { | |||
| 22403 | bar.barMaxWidthAmount = val_itr->value.GetInt(); | |||
| 22404 | } | |||
| 22405 | else if ( key == "bar_interval_to_increase_width" ) | |||
| 22406 | { | |||
| 22407 | bar.barIntervalToIncreaseWidth = val_itr->value.GetInt(); | |||
| 22408 | } | |||
| 22409 | else if ( key == "bar_interval_start_value" ) | |||
| 22410 | { | |||
| 22411 | bar.barIntervalStartValue = val_itr->value.GetInt(); | |||
| 22412 | } | |||
| 22413 | else if ( key == "bar_width_increase_percent_on_interval" ) | |||
| 22414 | { | |||
| 22415 | bar.barWidthIncreasePercentOnInterval = val_itr->value.GetDouble(); | |||
| 22416 | } | |||
| 22417 | else if ( key == "bar_base_percent" ) | |||
| 22418 | { | |||
| 22419 | bar.barBasePercentSize = val_itr->value.GetInt(); | |||
| 22420 | } | |||
| 22421 | else if ( key == "bar_compact_max_amount_threshold" ) | |||
| 22422 | { | |||
| 22423 | bar.barCompactMaxWidthAmount = val_itr->value.GetInt(); | |||
| 22424 | } | |||
| 22425 | else if ( key == "bar_compact_interval_to_increase_width" ) | |||
| 22426 | { | |||
| 22427 | bar.barCompactIntervalToIncreaseWidth = val_itr->value.GetInt(); | |||
| 22428 | } | |||
| 22429 | else if ( key == "bar_compact_interval_start_value" ) | |||
| 22430 | { | |||
| 22431 | bar.barCompactIntervalStartValue = val_itr->value.GetInt(); | |||
| 22432 | } | |||
| 22433 | else if ( key == "bar_compact_width_increase_percent_on_interval" ) | |||
| 22434 | { | |||
| 22435 | bar.barCompactWidthIncreasePercentOnInterval = val_itr->value.GetDouble(); | |||
| 22436 | } | |||
| 22437 | else if ( key == "bar_compact_base_percent" ) | |||
| 22438 | { | |||
| 22439 | bar.barCompactBasePercentSize = val_itr->value.GetInt(); | |||
| 22440 | } | |||
| 22441 | } | |||
| 22442 | } | |||
| 22443 | if ( ally_itr->value.HasMember("mp") ) | |||
| 22444 | { | |||
| 22445 | for ( auto val_itr = ally_itr->value["mp"].MemberBegin(); | |||
| 22446 | val_itr != ally_itr->value["mp"].MemberEnd(); ++val_itr ) | |||
| 22447 | { | |||
| 22448 | std::string key = val_itr->name.GetString(); | |||
| 22449 | auto& bar = AllyStatusBarSettings_t::PlayerBars_t::mpBar; | |||
| 22450 | if ( key == "bar_pixel_width" ) | |||
| 22451 | { | |||
| 22452 | bar.barPixelWidth = val_itr->value.GetInt(); | |||
| 22453 | } | |||
| 22454 | else if ( key == "bar_compact_pixel_width" ) | |||
| 22455 | { | |||
| 22456 | bar.barCompactPixelWidth = val_itr->value.GetInt(); | |||
| 22457 | } | |||
| 22458 | else if ( key == "bar_max_amount_threshold" ) | |||
| 22459 | { | |||
| 22460 | bar.barMaxWidthAmount = val_itr->value.GetInt(); | |||
| 22461 | } | |||
| 22462 | else if ( key == "bar_interval_to_increase_width" ) | |||
| 22463 | { | |||
| 22464 | bar.barIntervalToIncreaseWidth = val_itr->value.GetInt(); | |||
| 22465 | } | |||
| 22466 | else if ( key == "bar_interval_start_value" ) | |||
| 22467 | { | |||
| 22468 | bar.barIntervalStartValue = val_itr->value.GetInt(); | |||
| 22469 | } | |||
| 22470 | else if ( key == "bar_width_increase_percent_on_interval" ) | |||
| 22471 | { | |||
| 22472 | bar.barWidthIncreasePercentOnInterval = val_itr->value.GetDouble(); | |||
| 22473 | } | |||
| 22474 | else if ( key == "bar_base_percent" ) | |||
| 22475 | { | |||
| 22476 | bar.barBasePercentSize = val_itr->value.GetInt(); | |||
| 22477 | } | |||
| 22478 | else if ( key == "bar_compact_max_amount_threshold" ) | |||
| 22479 | { | |||
| 22480 | bar.barCompactMaxWidthAmount = val_itr->value.GetInt(); | |||
| 22481 | } | |||
| 22482 | else if ( key == "bar_compact_interval_to_increase_width" ) | |||
| 22483 | { | |||
| 22484 | bar.barCompactIntervalToIncreaseWidth = val_itr->value.GetInt(); | |||
| 22485 | } | |||
| 22486 | else if ( key == "bar_compact_interval_start_value" ) | |||
| 22487 | { | |||
| 22488 | bar.barCompactIntervalStartValue = val_itr->value.GetInt(); | |||
| 22489 | } | |||
| 22490 | else if ( key == "bar_compact_width_increase_percent_on_interval" ) | |||
| 22491 | { | |||
| 22492 | bar.barCompactWidthIncreasePercentOnInterval = val_itr->value.GetDouble(); | |||
| 22493 | } | |||
| 22494 | else if ( key == "bar_compact_base_percent" ) | |||
| 22495 | { | |||
| 22496 | bar.barCompactBasePercentSize = val_itr->value.GetInt(); | |||
| 22497 | } | |||
| 22498 | } | |||
| 22499 | } | |||
| 22500 | } | |||
| 22501 | } | |||
| 22502 | if ( d["hpmpbar"].HasMember("hpmpbar_max_amount_threshold") ) | |||
| 22503 | { | |||
| 22504 | hpmpbarMaxWidthAmount = d["hpmpbar"]["hpmpbar_max_amount_threshold"].GetInt(); | |||
| 22505 | } | |||
| 22506 | if ( d["hpmpbar"].HasMember("hpmpbar_interval_to_increase_width") ) | |||
| 22507 | { | |||
| 22508 | hpmpbarIntervalToIncreaseWidth | |||
| 22509 | = d["hpmpbar"]["hpmpbar_interval_to_increase_width"].GetInt(); | |||
| 22510 | } | |||
| 22511 | if ( d["hpmpbar"].HasMember("hpmpbar_base_percent") ) | |||
| 22512 | { | |||
| 22513 | hpmpbarBasePercentSize = d["hpmpbar"]["hpmpbar_base_percent"].GetInt(); | |||
| 22514 | } | |||
| 22515 | if ( d["hpmpbar"].HasMember("hpmpbar_interval_start_value") ) | |||
| 22516 | { | |||
| 22517 | hpmpbarIntervalStartValue = d["hpmpbar"]["hpmpbar_interval_start_value"].GetInt(); | |||
| 22518 | } | |||
| 22519 | if ( d["hpmpbar"].HasMember("hpmpbar_width_increase_percent_on_interval") ) | |||
| 22520 | { | |||
| 22521 | hpmpbarWidthIncreasePercentOnInterval = | |||
| 22522 | d["hpmpbar"]["hpmpbar_width_increase_percent_on_interval"].GetDouble(); | |||
| 22523 | } | |||
| 22524 | ||||
| 22525 | if ( d["hpmpbar"].HasMember("hpmpbar_compact_max_amount_threshold") ) | |||
| 22526 | { | |||
| 22527 | hpmpbarCompactMaxWidthAmount = d["hpmpbar"]["hpmpbar_compact_max_amount_threshold"].GetInt(); | |||
| 22528 | } | |||
| 22529 | if ( d["hpmpbar"].HasMember("hpmpbar_compact_interval_to_increase_width") ) | |||
| 22530 | { | |||
| 22531 | hpmpbarCompactIntervalToIncreaseWidth = | |||
| 22532 | d["hpmpbar"]["hpmpbar_compact_interval_to_increase_width"].GetInt(); | |||
| 22533 | } | |||
| 22534 | if ( d["hpmpbar"].HasMember("hpmpbar_compact_base_percent") ) | |||
| 22535 | { | |||
| 22536 | hpmpbarCompactBasePercentSize = d["hpmpbar"]["hpmpbar_compact_base_percent"].GetInt(); | |||
| 22537 | } | |||
| 22538 | if ( d["hpmpbar"].HasMember("hpmpbar_compact_interval_start_value") ) | |||
| 22539 | { | |||
| 22540 | hpmpbarCompactIntervalStartValue = d["hpmpbar"]["hpmpbar_compact_interval_start_value"].GetInt(); | |||
| 22541 | } | |||
| 22542 | if ( d["hpmpbar"].HasMember("hpmpbar_compact_width_increase_percent_on_interval") ) | |||
| 22543 | { | |||
| 22544 | hpmpbarCompactWidthIncreasePercentOnInterval = | |||
| 22545 | d["hpmpbar"]["hpmpbar_compact_width_increase_percent_on_interval"].GetDouble(); | |||
| 22546 | } | |||
| 22547 | } | |||
| 22548 | if ( d.HasMember("action_prompts") ) | |||
| 22549 | { | |||
| 22550 | if ( d["action_prompts"].HasMember("x_offset") ) | |||
| 22551 | { | |||
| 22552 | Player::HUD_t::actionPromptOffsetX = d["action_prompts"]["x_offset"].GetInt(); | |||
| 22553 | } | |||
| 22554 | if ( d["action_prompts"].HasMember("x_offset_ghost_prompts") ) | |||
| 22555 | { | |||
| 22556 | Player::HUD_t::actionPromptOffsetXGhostPrompts = d["action_prompts"]["x_offset_ghost_prompts"].GetInt(); | |||
| 22557 | } | |||
| 22558 | if ( d["action_prompts"].HasMember("y_offset") ) | |||
| 22559 | { | |||
| 22560 | Player::HUD_t::actionPromptOffsetY = d["action_prompts"]["y_offset"].GetInt(); | |||
| 22561 | } | |||
| 22562 | if ( d["action_prompts"].HasMember("icon_size") ) | |||
| 22563 | { | |||
| 22564 | Player::HUD_t::actionPromptIconSize = d["action_prompts"]["icon_size"].GetInt(); | |||
| 22565 | } | |||
| 22566 | if ( d["action_prompts"].HasMember("icon_backing_size") ) | |||
| 22567 | { | |||
| 22568 | Player::HUD_t::actionPromptBackingSize = d["action_prompts"]["icon_backing_size"].GetInt(); | |||
| 22569 | } | |||
| 22570 | if ( d["action_prompts"].HasMember("icon_opacity") ) | |||
| 22571 | { | |||
| 22572 | Player::HUD_t::actionPromptIconOpacity = d["action_prompts"]["icon_opacity"].GetInt(); | |||
| 22573 | } | |||
| 22574 | if ( d["action_prompts"].HasMember("icon_backing_opacity") ) | |||
| 22575 | { | |||
| 22576 | Player::HUD_t::actionPromptIconBackingOpacity = d["action_prompts"]["icon_backing_opacity"].GetInt(); | |||
| 22577 | } | |||
| 22578 | if ( d["action_prompts"].HasMember("prompt_img_00") ) | |||
| 22579 | { | |||
| 22580 | actionPromptBackingIconPath00 = d["action_prompts"]["prompt_img_00"].GetString(); | |||
| 22581 | } | |||
| 22582 | if ( d["action_prompts"].HasMember("prompt_img_20") ) | |||
| 22583 | { | |||
| 22584 | actionPromptBackingIconPath20 = d["action_prompts"]["prompt_img_20"].GetString(); | |||
| 22585 | } | |||
| 22586 | if ( d["action_prompts"].HasMember("prompt_img_60") ) | |||
| 22587 | { | |||
| 22588 | actionPromptBackingIconPath60 = d["action_prompts"]["prompt_img_60"].GetString(); | |||
| 22589 | } | |||
| 22590 | if ( d["action_prompts"].HasMember("prompt_img_100") ) | |||
| 22591 | { | |||
| 22592 | actionPromptBackingIconPath100 = d["action_prompts"]["prompt_img_100"].GetString(); | |||
| 22593 | } | |||
| 22594 | } | |||
| 22595 | if ( d.HasMember("world_items") ) | |||
| 22596 | { | |||
| 22597 | if ( d["world_items"].HasMember("scale_modifier") ) | |||
| 22598 | { | |||
| 22599 | Player::WorldUI_t::WorldTooltipItem_t::WorldItemSettings_t::scaleMod = d["world_items"]["scale_modifier"].GetDouble(); | |||
| 22600 | } | |||
| 22601 | if ( d["world_items"].HasMember("tooltip_opacity") ) | |||
| 22602 | { | |||
| 22603 | Player::WorldUI_t::WorldTooltipItem_t::WorldItemSettings_t::opacity = d["world_items"]["tooltip_opacity"].GetDouble(); | |||
| 22604 | } | |||
| 22605 | } | |||
| 22606 | if ( d.HasMember("minimap") ) | |||
| 22607 | { | |||
| 22608 | if ( d["minimap"].HasMember("minimap_full_default_size") ) | |||
| 22609 | { | |||
| 22610 | Player::Minimap_t::fullSize = d["minimap"]["minimap_full_default_size"].GetInt(); | |||
| 22611 | } | |||
| 22612 | if ( d["minimap"].HasMember("minimap_compact_default_size") ) | |||
| 22613 | { | |||
| 22614 | Player::Minimap_t::compactSize = d["minimap"]["minimap_compact_default_size"].GetInt(); | |||
| 22615 | } | |||
| 22616 | if ( d["minimap"].HasMember("minimap_compact_2p_vertical_size") ) | |||
| 22617 | { | |||
| 22618 | Player::Minimap_t::compact2pVerticalSize = d["minimap"]["minimap_compact_2p_vertical_size"].GetInt(); | |||
| 22619 | } | |||
| 22620 | ||||
| 22621 | if ( d["minimap"].HasMember("minimap_full_big_scale") ) | |||
| 22622 | { | |||
| 22623 | Player::Minimap_t::fullBigScale = d["minimap"]["minimap_full_big_scale"].GetDouble(); | |||
| 22624 | } | |||
| 22625 | if ( d["minimap"].HasMember("minimap_compact_big_scale") ) | |||
| 22626 | { | |||
| 22627 | Player::Minimap_t::compactBigScale = d["minimap"]["minimap_compact_big_scale"].GetDouble(); | |||
| 22628 | } | |||
| 22629 | if ( d["minimap"].HasMember("minimap_compact_2p_vertical_big_scale") ) | |||
| 22630 | { | |||
| 22631 | Player::Minimap_t::compact2pVerticalBigScale = d["minimap"]["minimap_compact_2p_vertical_big_scale"].GetDouble(); | |||
| 22632 | } | |||
| 22633 | } | |||
| 22634 | if ( d.HasMember("levelup_anim_curve") ) | |||
| 22635 | { | |||
| 22636 | LevelUpAnimBreakpoints.clear(); | |||
| 22637 | for ( auto it = d["levelup_anim_curve"].Begin(); it != d["levelup_anim_curve"].End(); ++it ) | |||
| 22638 | { | |||
| 22639 | LevelUpAnimBreakpoints.push_back(it->GetInt()); | |||
| 22640 | } | |||
| 22641 | } | |||
| 22642 | if ( d.HasMember("dmg_number_anim_curve") ) | |||
| 22643 | { | |||
| 22644 | EnemyHPDamageBarHandler::damageGibAnimCurves.clear(); | |||
| 22645 | for ( auto it = d["dmg_number_anim_curve"].MemberBegin(); it != d["dmg_number_anim_curve"].MemberEnd(); ++it ) | |||
| 22646 | { | |||
| 22647 | std::string name = it->name.GetString(); | |||
| 22648 | if ( name == "default" ) | |||
| 22649 | { | |||
| 22650 | for ( auto it2 = it->value.Begin(); it2 != it->value.End(); ++it2 ) | |||
| 22651 | { | |||
| 22652 | EnemyHPDamageBarHandler::damageGibAnimCurves[DMG_DEFAULT].push_back(it2->GetInt()); | |||
| 22653 | } | |||
| 22654 | } | |||
| 22655 | } | |||
| 22656 | } | |||
| 22657 | if ( d.HasMember("damage_indicators") ) | |||
| 22658 | { | |||
| 22659 | damageIndicatorSettings.settings.clear(); | |||
| 22660 | if ( d["damage_indicators"].HasMember("delete_after_ticks") ) | |||
| 22661 | { | |||
| 22662 | damageIndicatorSettings.deleteAfterTicks = d["damage_indicators"]["delete_after_ticks"].GetUint(); | |||
| 22663 | } | |||
| 22664 | if ( d["damage_indicators"].HasMember("fade_after_ticks") ) | |||
| 22665 | { | |||
| 22666 | damageIndicatorSettings.fadeAfterTicks = d["damage_indicators"]["fade_after_ticks"].GetUint(); | |||
| 22667 | } | |||
| 22668 | if ( d["damage_indicators"].HasMember("fade_speed") ) | |||
| 22669 | { | |||
| 22670 | damageIndicatorSettings.fadeSpeed = d["damage_indicators"]["fade_speed"].GetDouble(); | |||
| 22671 | } | |||
| 22672 | if ( d["damage_indicators"].HasMember("animation_on_damage") ) | |||
| 22673 | { | |||
| 22674 | int index = 0; | |||
| 22675 | for ( auto it = d["damage_indicators"]["animation_on_damage"].Begin(); it != d["damage_indicators"]["animation_on_damage"].End(); ++it ) | |||
| 22676 | { | |||
| 22677 | damageIndicatorSettings.indicatorDamageFramePaths[index] = it->GetString(); | |||
| 22678 | ++index; | |||
| 22679 | if ( index >= 4 ) | |||
| 22680 | { | |||
| 22681 | break; | |||
| 22682 | } | |||
| 22683 | } | |||
| 22684 | } | |||
| 22685 | if ( d["damage_indicators"].HasMember("animation_on_blocking") ) | |||
| 22686 | { | |||
| 22687 | int index = 0; | |||
| 22688 | for ( auto it = d["damage_indicators"]["animation_on_blocking"].Begin(); it != d["damage_indicators"]["animation_on_blocking"].End(); ++it ) | |||
| 22689 | { | |||
| 22690 | damageIndicatorSettings.indicatorBlockedFramePaths[index] = it->GetString(); | |||
| 22691 | ++index; | |||
| 22692 | if ( index >= 4 ) | |||
| 22693 | { | |||
| 22694 | break; | |||
| 22695 | } | |||
| 22696 | } | |||
| 22697 | } | |||
| 22698 | if ( d["damage_indicators"].HasMember("layout_default") ) | |||
| 22699 | { | |||
| 22700 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_DEFAULT] = | |||
| 22701 | DamageIndicatorSettings_t::Layout_t(); | |||
| 22702 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_DEFAULT].image_size | |||
| 22703 | = d["damage_indicators"]["layout_default"]["image_size"].GetInt(); | |||
| 22704 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_DEFAULT].radius_x | |||
| 22705 | = d["damage_indicators"]["layout_default"]["radius_x"].GetInt(); | |||
| 22706 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_DEFAULT].radius_y | |||
| 22707 | = d["damage_indicators"]["layout_default"]["radius_y"].GetInt(); | |||
| 22708 | } | |||
| 22709 | if ( d["damage_indicators"].HasMember("layout_2p_tall") ) | |||
| 22710 | { | |||
| 22711 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_2P_TALL] = | |||
| 22712 | DamageIndicatorSettings_t::Layout_t(); | |||
| 22713 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_2P_TALL].image_size | |||
| 22714 | = d["damage_indicators"]["layout_2p_tall"]["image_size"].GetInt(); | |||
| 22715 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_2P_TALL].radius_x | |||
| 22716 | = d["damage_indicators"]["layout_2p_tall"]["radius_x"].GetInt(); | |||
| 22717 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_2P_TALL].radius_y | |||
| 22718 | = d["damage_indicators"]["layout_2p_tall"]["radius_y"].GetInt(); | |||
| 22719 | } | |||
| 22720 | if ( d["damage_indicators"].HasMember("layout_2p_wide") ) | |||
| 22721 | { | |||
| 22722 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_2P_WIDE] = | |||
| 22723 | DamageIndicatorSettings_t::Layout_t(); | |||
| 22724 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_2P_WIDE].image_size | |||
| 22725 | = d["damage_indicators"]["layout_2p_wide"]["image_size"].GetInt(); | |||
| 22726 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_2P_WIDE].radius_x | |||
| 22727 | = d["damage_indicators"]["layout_2p_wide"]["radius_x"].GetInt(); | |||
| 22728 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_2P_WIDE].radius_y | |||
| 22729 | = d["damage_indicators"]["layout_2p_wide"]["radius_y"].GetInt(); | |||
| 22730 | } | |||
| 22731 | if ( d["damage_indicators"].HasMember("layout_4p") ) | |||
| 22732 | { | |||
| 22733 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_4P] = | |||
| 22734 | DamageIndicatorSettings_t::Layout_t(); | |||
| 22735 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_4P].image_size | |||
| 22736 | = d["damage_indicators"]["layout_4p"]["image_size"].GetInt(); | |||
| 22737 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_4P].radius_x | |||
| 22738 | = d["damage_indicators"]["layout_4p"]["radius_x"].GetInt(); | |||
| 22739 | damageIndicatorSettings.settings[DamageIndicatorSettings_t::LAYOUT_4P].radius_y | |||
| 22740 | = d["damage_indicators"]["layout_4p"]["radius_y"].GetInt(); | |||
| 22741 | } | |||
| 22742 | } | |||
| 22743 | if ( d.HasMember("messages") ) | |||
| 22744 | { | |||
| 22745 | messageZoneSettings.settings.clear(); | |||
| 22746 | std::vector<std::pair<const char*, MessageZoneSettings_t::HotbarTypes_t>> hotbarTypeStrings = { | |||
| 22747 | {"classic_hotbar", MessageZoneSettings_t::HOTBAR_CLASSIC }, | |||
| 22748 | {"modern_hotbar_keyboard", MessageZoneSettings_t::HOTBAR_MODERN_KEYBOARD }, | |||
| 22749 | {"modern_hotbar_gamepad", MessageZoneSettings_t::HOTBAR_MODERN_GAMEPAD } | |||
| 22750 | }; | |||
| 22751 | ||||
| 22752 | for ( auto pair : hotbarTypeStrings ) | |||
| 22753 | { | |||
| 22754 | if ( d["messages"].HasMember(pair.first) ) | |||
| 22755 | { | |||
| 22756 | for ( rapidjson::Value::ConstMemberIterator itr = d["messages"][pair.first].MemberBegin(); | |||
| 22757 | itr != d["messages"][pair.first].MemberEnd(); ++itr ) | |||
| 22758 | { | |||
| 22759 | std::string alignmentStr = itr->name.GetString(); | |||
| 22760 | auto alignment = Player::MessageZone_t::ALIGN_LEFT_BOTTOM; | |||
| 22761 | if ( alignmentStr == "left_top" ) | |||
| 22762 | { | |||
| 22763 | alignment = Player::MessageZone_t::ALIGN_LEFT_TOP; | |||
| 22764 | } | |||
| 22765 | else if ( alignmentStr == "left_bottom" ) | |||
| 22766 | { | |||
| 22767 | alignment = Player::MessageZone_t::ALIGN_LEFT_BOTTOM; | |||
| 22768 | } | |||
| 22769 | else if ( alignmentStr == "center_bottom" ) | |||
| 22770 | { | |||
| 22771 | alignment = Player::MessageZone_t::ALIGN_CENTER_BOTTOM; | |||
| 22772 | } | |||
| 22773 | else | |||
| 22774 | { | |||
| 22775 | continue; | |||
| 22776 | } | |||
| 22777 | ||||
| 22778 | auto& setting = messageZoneSettings.addSetting(pair.second, alignment); | |||
| 22779 | for ( rapidjson::Value::ConstMemberIterator itr2 = itr->value.MemberBegin(); | |||
| 22780 | itr2 != itr->value.MemberEnd(); ++itr2 ) | |||
| 22781 | { | |||
| 22782 | std::string layoutStr = itr2->name.GetString(); | |||
| 22783 | auto layout = MessageZoneSettings_t::MessageSettings_t::LAYOUT_DEFAULT; | |||
| 22784 | if ( layoutStr == "default" ) | |||
| 22785 | { | |||
| 22786 | layout = MessageZoneSettings_t::MessageSettings_t::LAYOUT_DEFAULT; | |||
| 22787 | } | |||
| 22788 | else if ( layoutStr == "compact_height" ) | |||
| 22789 | { | |||
| 22790 | layout = MessageZoneSettings_t::MessageSettings_t::LAYOUT_COMPACT; | |||
| 22791 | } | |||
| 22792 | else | |||
| 22793 | { | |||
| 22794 | continue; | |||
| 22795 | } | |||
| 22796 | setting.layouts[layout].layoutType = layout; | |||
| 22797 | setting.layouts[layout].offsetY = itr2->value["y_offset"].GetInt(); | |||
| 22798 | setting.layouts[layout].maxMessages = itr2->value["max_messages"].GetInt(); | |||
| 22799 | } | |||
| 22800 | } | |||
| 22801 | } | |||
| 22802 | } | |||
| 22803 | } | |||
| 22804 | if ( d.HasMember("world_dialogue") ) | |||
| 22805 | { | |||
| 22806 | if ( d["world_dialogue"].HasMember("types") ) | |||
| 22807 | { | |||
| 22808 | for ( rapidjson::Value::ConstMemberIterator itr = d["world_dialogue"]["types"].MemberBegin(); | |||
| 22809 | itr != d["world_dialogue"]["types"].MemberEnd(); ++itr ) | |||
| 22810 | { | |||
| 22811 | std::string type = itr->name.GetString(); | |||
| 22812 | auto dialogueType = Player::WorldUI_t::WorldTooltipDialogue_t::DIALOGUE_NONE; | |||
| 22813 | if ( type == "default" ) | |||
| 22814 | { | |||
| 22815 | dialogueType = Player::WorldUI_t::WorldTooltipDialogue_t::DIALOGUE_NONE; | |||
| 22816 | } | |||
| 22817 | else if ( type == "grave" ) | |||
| 22818 | { | |||
| 22819 | dialogueType = Player::WorldUI_t::WorldTooltipDialogue_t::DIALOGUE_GRAVE; | |||
| 22820 | } | |||
| 22821 | else if ( type == "signpost" ) | |||
| 22822 | { | |||
| 22823 | dialogueType = Player::WorldUI_t::WorldTooltipDialogue_t::DIALOGUE_SIGNPOST; | |||
| 22824 | } | |||
| 22825 | else if ( type == "human_npc" ) | |||
| 22826 | { | |||
| 22827 | dialogueType = Player::WorldUI_t::WorldTooltipDialogue_t::DIALOGUE_NPC; | |||
| 22828 | } | |||
| 22829 | else if ( type == "follower_cmd" ) | |||
| 22830 | { | |||
| 22831 | dialogueType = Player::WorldUI_t::WorldTooltipDialogue_t::DIALOGUE_FOLLOWER_CMD; | |||
| 22832 | } | |||
| 22833 | else if ( type == "broadcast" ) | |||
| 22834 | { | |||
| 22835 | dialogueType = Player::WorldUI_t::WorldTooltipDialogue_t::DIALOGUE_BROADCAST; | |||
| 22836 | } | |||
| 22837 | else if ( type == "attack" ) | |||
| 22838 | { | |||
| 22839 | dialogueType = Player::WorldUI_t::WorldTooltipDialogue_t::DIALOGUE_ATTACK; | |||
| 22840 | } | |||
| 22841 | else | |||
| 22842 | { | |||
| 22843 | continue; | |||
| 22844 | } | |||
| 22845 | ||||
| 22846 | auto& settings = Player::WorldUI_t::WorldTooltipDialogue_t::WorldDialogueSettings_t::settings[dialogueType]; | |||
| 22847 | if ( itr->value.HasMember("z_offset") ) | |||
| 22848 | { | |||
| 22849 | settings.offsetZ = itr->value["z_offset"].GetDouble(); | |||
| 22850 | } | |||
| 22851 | if ( itr->value.HasMember("text_delay") ) | |||
| 22852 | { | |||
| 22853 | settings.textDelay = itr->value["text_delay"].GetInt(); | |||
| 22854 | } | |||
| 22855 | if ( itr->value.HasMember("follow_entity") ) | |||
| 22856 | { | |||
| 22857 | settings.followEntity = itr->value["follow_entity"].GetBool(); | |||
| 22858 | } | |||
| 22859 | if ( itr->value.HasMember("fade_dist") ) | |||
| 22860 | { | |||
| 22861 | settings.fadeDist = itr->value["fade_dist"].GetDouble(); | |||
| 22862 | } | |||
| 22863 | if ( itr->value.HasMember("base_ticks_to_display") ) | |||
| 22864 | { | |||
| 22865 | settings.baseTicksToDisplay = itr->value["base_ticks_to_display"].GetUint(); | |||
| 22866 | } | |||
| 22867 | if ( itr->value.HasMember("extra_ticks_per_line") ) | |||
| 22868 | { | |||
| 22869 | settings.extraTicksPerLine = itr->value["extra_ticks_per_line"].GetUint(); | |||
| 22870 | } | |||
| 22871 | if ( itr->value.HasMember("max_width") ) | |||
| 22872 | { | |||
| 22873 | settings.maxWidth = itr->value["max_width"].GetInt(); | |||
| 22874 | } | |||
| 22875 | if ( itr->value.HasMember("padx") ) | |||
| 22876 | { | |||
| 22877 | settings.padx = itr->value["padx"].GetInt(); | |||
| 22878 | } | |||
| 22879 | if ( itr->value.HasMember("pady") ) | |||
| 22880 | { | |||
| 22881 | settings.pady = itr->value["pady"].GetInt(); | |||
| 22882 | } | |||
| 22883 | if ( itr->value.HasMember("pad_after_first_line") ) | |||
| 22884 | { | |||
| 22885 | settings.padAfterFirstLine = itr->value["pad_after_first_line"].GetInt(); | |||
| 22886 | } | |||
| 22887 | if ( itr->value.HasMember("scale_modifier") ) | |||
| 22888 | { | |||
| 22889 | settings.scaleMod = itr->value["scale_modifier"].GetDouble(); | |||
| 22890 | } | |||
| 22891 | } | |||
| 22892 | } | |||
| 22893 | } | |||
| 22894 | if ( d.HasMember("enemy_hp_bars") ) | |||
| 22895 | { | |||
| 22896 | if ( d["enemy_hp_bars"].HasMember("world_height_offsets") ) | |||
| 22897 | { | |||
| 22898 | enemyBarSettings.heightOffsets.clear(); | |||
| 22899 | for ( rapidjson::Value::ConstMemberIterator itr = d["enemy_hp_bars"]["world_height_offsets"].MemberBegin(); | |||
| 22900 | itr != d["enemy_hp_bars"]["world_height_offsets"].MemberEnd(); ++itr ) | |||
| 22901 | { | |||
| 22902 | enemyBarSettings.heightOffsets[itr->name.GetString()] = itr->value.GetFloat(); | |||
| 22903 | } | |||
| 22904 | } | |||
| 22905 | if ( d["enemy_hp_bars"].HasMember("screen_depth_distance_offset") ) | |||
| 22906 | { | |||
| 22907 | enemyBarSettings.screenDistanceOffsets.clear(); | |||
| 22908 | for ( rapidjson::Value::ConstMemberIterator itr = d["enemy_hp_bars"]["screen_depth_distance_offset"].MemberBegin(); | |||
| 22909 | itr != d["enemy_hp_bars"]["screen_depth_distance_offset"].MemberEnd(); ++itr ) | |||
| 22910 | { | |||
| 22911 | enemyBarSettings.screenDistanceOffsets[itr->name.GetString()] = itr->value.GetFloat(); | |||
| 22912 | } | |||
| 22913 | } | |||
| 22914 | if ( d["enemy_hp_bars"].HasMember("monster_bar_width_to_hp_intervals") ) | |||
| 22915 | { | |||
| 22916 | EnemyHPDamageBarHandler::widthHealthBreakpointsMonsters.clear(); | |||
| 22917 | for ( rapidjson::Value::ConstValueIterator itr = d["enemy_hp_bars"]["monster_bar_width_to_hp_intervals"].Begin(); | |||
| 22918 | itr != d["enemy_hp_bars"]["monster_bar_width_to_hp_intervals"].End(); ++itr ) | |||
| 22919 | { | |||
| 22920 | // you need to FindMember() if getting objects from an array... | |||
| 22921 | auto widthPercentMember = itr->FindMember("width_percent"); | |||
| 22922 | auto hpThresholdMember = itr->FindMember("hp_threshold"); | |||
| 22923 | if ( !widthPercentMember->value.IsInt() || !hpThresholdMember->value.IsInt() ) | |||
| 22924 | { | |||
| 22925 | printlog("[JSON]: Error: Enemy bar HP or width was not int!"); | |||
| 22926 | continue; | |||
| 22927 | } | |||
| 22928 | real_t widthPercent = widthPercentMember->value.GetInt(); | |||
| 22929 | widthPercent /= 100.0; | |||
| 22930 | int hpThreshold = hpThresholdMember->value.GetInt(); | |||
| 22931 | EnemyHPDamageBarHandler::widthHealthBreakpointsMonsters.push_back( | |||
| 22932 | std::make_pair(widthPercent, hpThreshold)); | |||
| 22933 | } | |||
| 22934 | } | |||
| 22935 | if ( d["enemy_hp_bars"].HasMember("furniture_bar_width_to_hp_intervals") ) | |||
| 22936 | { | |||
| 22937 | EnemyHPDamageBarHandler::widthHealthBreakpointsFurniture.clear(); | |||
| 22938 | for ( rapidjson::Value::ConstValueIterator itr = d["enemy_hp_bars"]["furniture_bar_width_to_hp_intervals"].Begin(); | |||
| 22939 | itr != d["enemy_hp_bars"]["furniture_bar_width_to_hp_intervals"].End(); ++itr ) | |||
| 22940 | { | |||
| 22941 | // you need to FindMember() if getting objects from an array... | |||
| 22942 | auto widthPercentMember = itr->FindMember("width_percent"); | |||
| 22943 | auto hpThresholdMember = itr->FindMember("hp_threshold"); | |||
| 22944 | if ( !widthPercentMember->value.IsInt() || !hpThresholdMember->value.IsInt() ) | |||
| 22945 | { | |||
| 22946 | printlog("[JSON]: Error: Enemy bar HP or width was not int!"); | |||
| 22947 | continue; | |||
| 22948 | } | |||
| 22949 | real_t widthPercent = widthPercentMember->value.GetInt(); | |||
| 22950 | widthPercent /= 100.0; | |||
| 22951 | int hpThreshold = hpThresholdMember->value.GetInt(); | |||
| 22952 | EnemyHPDamageBarHandler::widthHealthBreakpointsFurniture.push_back( | |||
| 22953 | std::make_pair(widthPercent, hpThreshold)); | |||
| 22954 | } | |||
| 22955 | } | |||
| 22956 | if ( d["enemy_hp_bars"].HasMember("monster_bar_lifetime_ticks") ) | |||
| 22957 | { | |||
| 22958 | EnemyHPDamageBarHandler::maxTickLifetime = d["enemy_hp_bars"]["monster_bar_lifetime_ticks"].GetInt(); | |||
| 22959 | } | |||
| 22960 | if ( d["enemy_hp_bars"].HasMember("furniture_bar_lifetime_ticks") ) | |||
| 22961 | { | |||
| 22962 | EnemyHPDamageBarHandler::maxTickFurnitureLifetime = d["enemy_hp_bars"]["furniture_bar_lifetime_ticks"].GetInt(); | |||
| 22963 | } | |||
| 22964 | if ( d["enemy_hp_bars"].HasMember("quick_fade_delay_ticks") ) | |||
| 22965 | { | |||
| 22966 | EnemyHPDamageBarHandler::shortDistanceHPBarFadeTicks = d["enemy_hp_bars"]["quick_fade_delay_ticks"].GetInt(); | |||
| 22967 | } | |||
| 22968 | if ( d["enemy_hp_bars"].HasMember("quick_fade_distance_from_player_multiplier") ) | |||
| 22969 | { | |||
| 22970 | if ( d["enemy_hp_bars"]["quick_fade_distance_from_player_multiplier"].IsDouble() ) | |||
| 22971 | { | |||
| 22972 | EnemyHPDamageBarHandler::shortDistanceHPBarFadeDistance = d["enemy_hp_bars"]["quick_fade_distance_from_player_multiplier"].GetDouble(); | |||
| 22973 | } | |||
| 22974 | else | |||
| 22975 | { | |||
| 22976 | EnemyHPDamageBarHandler::shortDistanceHPBarFadeDistance = d["enemy_hp_bars"]["quick_fade_distance_from_player_multiplier"].GetInt(); | |||
| 22977 | } | |||
| 22978 | } | |||
| 22979 | } | |||
| 22980 | if ( d.HasMember("colors") ) | |||
| 22981 | { | |||
| 22982 | if ( d["colors"].HasMember("itemmenu_heading_text") ) | |||
| 22983 | { | |||
| 22984 | hudColors.itemContextMenuHeadingText = makeColor( | |||
| 22985 | d["colors"]["itemmenu_heading_text"]["r"].GetInt(), | |||
| 22986 | d["colors"]["itemmenu_heading_text"]["g"].GetInt(), | |||
| 22987 | d["colors"]["itemmenu_heading_text"]["b"].GetInt(), | |||
| 22988 | d["colors"]["itemmenu_heading_text"]["a"].GetInt()); | |||
| 22989 | } | |||
| 22990 | if ( d["colors"].HasMember("itemmenu_option_text") ) | |||
| 22991 | { | |||
| 22992 | hudColors.itemContextMenuOptionText = makeColor( | |||
| 22993 | d["colors"]["itemmenu_option_text"]["r"].GetInt(), | |||
| 22994 | d["colors"]["itemmenu_option_text"]["g"].GetInt(), | |||
| 22995 | d["colors"]["itemmenu_option_text"]["b"].GetInt(), | |||
| 22996 | d["colors"]["itemmenu_option_text"]["a"].GetInt()); | |||
| 22997 | } | |||
| 22998 | if ( d["colors"].HasMember("itemmenu_selected_text") ) | |||
| 22999 | { | |||
| 23000 | hudColors.itemContextMenuOptionSelectedText = makeColor( | |||
| 23001 | d["colors"]["itemmenu_selected_text"]["r"].GetInt(), | |||
| 23002 | d["colors"]["itemmenu_selected_text"]["g"].GetInt(), | |||
| 23003 | d["colors"]["itemmenu_selected_text"]["b"].GetInt(), | |||
| 23004 | d["colors"]["itemmenu_selected_text"]["a"].GetInt()); | |||
| 23005 | } | |||
| 23006 | if ( d["colors"].HasMember("itemmenu_selected_img") ) | |||
| 23007 | { | |||
| 23008 | hudColors.itemContextMenuOptionSelectedImg = makeColor( | |||
| 23009 | d["colors"]["itemmenu_selected_img"]["r"].GetInt(), | |||
| 23010 | d["colors"]["itemmenu_selected_img"]["g"].GetInt(), | |||
| 23011 | d["colors"]["itemmenu_selected_img"]["b"].GetInt(), | |||
| 23012 | d["colors"]["itemmenu_selected_img"]["a"].GetInt()); | |||
| 23013 | } | |||
| 23014 | if ( d["colors"].HasMember("itemmenu_option_img") ) | |||
| 23015 | { | |||
| 23016 | hudColors.itemContextMenuOptionImg = makeColor( | |||
| 23017 | d["colors"]["itemmenu_option_img"]["r"].GetInt(), | |||
| 23018 | d["colors"]["itemmenu_option_img"]["g"].GetInt(), | |||
| 23019 | d["colors"]["itemmenu_option_img"]["b"].GetInt(), | |||
| 23020 | d["colors"]["itemmenu_option_img"]["a"].GetInt()); | |||
| 23021 | } | |||
| 23022 | if ( d["colors"].HasMember("charsheet_neutral_text") ) | |||
| 23023 | { | |||
| 23024 | hudColors.characterSheetNeutral = makeColor( | |||
| 23025 | d["colors"]["charsheet_neutral_text"]["r"].GetInt(), | |||
| 23026 | d["colors"]["charsheet_neutral_text"]["g"].GetInt(), | |||
| 23027 | d["colors"]["charsheet_neutral_text"]["b"].GetInt(), | |||
| 23028 | d["colors"]["charsheet_neutral_text"]["a"].GetInt()); | |||
| 23029 | } | |||
| 23030 | if ( d["colors"].HasMember("charsheet_neutral_light_text") ) | |||
| 23031 | { | |||
| 23032 | hudColors.characterSheetLightNeutral = makeColor( | |||
| 23033 | d["colors"]["charsheet_neutral_light_text"]["r"].GetInt(), | |||
| 23034 | d["colors"]["charsheet_neutral_light_text"]["g"].GetInt(), | |||
| 23035 | d["colors"]["charsheet_neutral_light_text"]["b"].GetInt(), | |||
| 23036 | d["colors"]["charsheet_neutral_light_text"]["a"].GetInt()); | |||
| 23037 | } | |||
| 23038 | if ( d["colors"].HasMember("charsheet_neutral_lighter1_text") ) | |||
| 23039 | { | |||
| 23040 | hudColors.characterSheetLighter1Neutral = makeColor( | |||
| 23041 | d["colors"]["charsheet_neutral_lighter1_text"]["r"].GetInt(), | |||
| 23042 | d["colors"]["charsheet_neutral_lighter1_text"]["g"].GetInt(), | |||
| 23043 | d["colors"]["charsheet_neutral_lighter1_text"]["b"].GetInt(), | |||
| 23044 | d["colors"]["charsheet_neutral_lighter1_text"]["a"].GetInt()); | |||
| 23045 | } | |||
| 23046 | if ( d["colors"].HasMember("charsheet_neutral_darker1_text") ) | |||
| 23047 | { | |||
| 23048 | hudColors.characterSheetDarker1Neutral = makeColor( | |||
| 23049 | d["colors"]["charsheet_neutral_darker1_text"]["r"].GetInt(), | |||
| 23050 | d["colors"]["charsheet_neutral_darker1_text"]["g"].GetInt(), | |||
| 23051 | d["colors"]["charsheet_neutral_darker1_text"]["b"].GetInt(), | |||
| 23052 | d["colors"]["charsheet_neutral_darker1_text"]["a"].GetInt()); | |||
| 23053 | } | |||
| 23054 | if ( d["colors"].HasMember("charsheet_positive_text") ) | |||
| 23055 | { | |||
| 23056 | hudColors.characterSheetGreen = makeColor( | |||
| 23057 | d["colors"]["charsheet_positive_text"]["r"].GetInt(), | |||
| 23058 | d["colors"]["charsheet_positive_text"]["g"].GetInt(), | |||
| 23059 | d["colors"]["charsheet_positive_text"]["b"].GetInt(), | |||
| 23060 | d["colors"]["charsheet_positive_text"]["a"].GetInt()); | |||
| 23061 | } | |||
| 23062 | if ( d["colors"].HasMember("charsheet_negative_text") ) | |||
| 23063 | { | |||
| 23064 | hudColors.characterSheetRed = makeColor( | |||
| 23065 | d["colors"]["charsheet_negative_text"]["r"].GetInt(), | |||
| 23066 | d["colors"]["charsheet_negative_text"]["g"].GetInt(), | |||
| 23067 | d["colors"]["charsheet_negative_text"]["b"].GetInt(), | |||
| 23068 | d["colors"]["charsheet_negative_text"]["a"].GetInt()); | |||
| 23069 | } | |||
| 23070 | if ( d["colors"].HasMember("charsheet_faint_text") ) | |||
| 23071 | { | |||
| 23072 | hudColors.characterSheetFaintText = makeColor( | |||
| 23073 | d["colors"]["charsheet_faint_text"]["r"].GetInt(), | |||
| 23074 | d["colors"]["charsheet_faint_text"]["g"].GetInt(), | |||
| 23075 | d["colors"]["charsheet_faint_text"]["b"].GetInt(), | |||
| 23076 | d["colors"]["charsheet_faint_text"]["a"].GetInt()); | |||
| 23077 | } | |||
| 23078 | if ( d["colors"].HasMember("charsheet_off_white_text") ) | |||
| 23079 | { | |||
| 23080 | hudColors.characterSheetOffWhiteText = makeColor( | |||
| 23081 | d["colors"]["charsheet_off_white_text"]["r"].GetInt(), | |||
| 23082 | d["colors"]["charsheet_off_white_text"]["g"].GetInt(), | |||
| 23083 | d["colors"]["charsheet_off_white_text"]["b"].GetInt(), | |||
| 23084 | d["colors"]["charsheet_off_white_text"]["a"].GetInt()); | |||
| 23085 | } | |||
| 23086 | if ( d["colors"].HasMember("charsheet_heading_text") ) | |||
| 23087 | { | |||
| 23088 | hudColors.characterSheetHeadingText = makeColor( | |||
| 23089 | d["colors"]["charsheet_heading_text"]["r"].GetInt(), | |||
| 23090 | d["colors"]["charsheet_heading_text"]["g"].GetInt(), | |||
| 23091 | d["colors"]["charsheet_heading_text"]["b"].GetInt(), | |||
| 23092 | d["colors"]["charsheet_heading_text"]["a"].GetInt()); | |||
| 23093 | } | |||
| 23094 | if ( d["colors"].HasMember("charsheet_highlight_text") ) | |||
| 23095 | { | |||
| 23096 | hudColors.characterSheetHighlightText = makeColor( | |||
| 23097 | d["colors"]["charsheet_highlight_text"]["r"].GetInt(), | |||
| 23098 | d["colors"]["charsheet_highlight_text"]["g"].GetInt(), | |||
| 23099 | d["colors"]["charsheet_highlight_text"]["b"].GetInt(), | |||
| 23100 | d["colors"]["charsheet_highlight_text"]["a"].GetInt()); | |||
| 23101 | } | |||
| 23102 | if ( d["colors"].HasMember("charsheet_base_class_text") ) | |||
| 23103 | { | |||
| 23104 | hudColors.characterBaseClassText = makeColor( | |||
| 23105 | d["colors"]["charsheet_base_class_text"]["r"].GetInt(), | |||
| 23106 | d["colors"]["charsheet_base_class_text"]["g"].GetInt(), | |||
| 23107 | d["colors"]["charsheet_base_class_text"]["b"].GetInt(), | |||
| 23108 | d["colors"]["charsheet_base_class_text"]["a"].GetInt()); | |||
| 23109 | } | |||
| 23110 | if ( d["colors"].HasMember("charsheet_dlc1_text") ) | |||
| 23111 | { | |||
| 23112 | hudColors.characterDLC1ClassText = makeColor( | |||
| 23113 | d["colors"]["charsheet_dlc1_text"]["r"].GetInt(), | |||
| 23114 | d["colors"]["charsheet_dlc1_text"]["g"].GetInt(), | |||
| 23115 | d["colors"]["charsheet_dlc1_text"]["b"].GetInt(), | |||
| 23116 | d["colors"]["charsheet_dlc1_text"]["a"].GetInt()); | |||
| 23117 | } | |||
| 23118 | if ( d["colors"].HasMember("charsheet_dlc2_text") ) | |||
| 23119 | { | |||
| 23120 | hudColors.characterDLC2ClassText = makeColor( | |||
| 23121 | d["colors"]["charsheet_dlc2_text"]["r"].GetInt(), | |||
| 23122 | d["colors"]["charsheet_dlc2_text"]["g"].GetInt(), | |||
| 23123 | d["colors"]["charsheet_dlc2_text"]["b"].GetInt(), | |||
| 23124 | d["colors"]["charsheet_dlc2_text"]["a"].GetInt()); | |||
| 23125 | } | |||
| 23126 | } | |||
| 23127 | if ( d.HasMember("dropdowns") ) | |||
| 23128 | { | |||
| 23129 | Player::GUIDropdown_t::allDropDowns.clear(); | |||
| 23130 | for ( rapidjson::Value::ConstMemberIterator itr = d["dropdowns"].MemberBegin(); | |||
| 23131 | itr != d["dropdowns"].MemberEnd(); ++itr ) | |||
| 23132 | { | |||
| 23133 | auto& dropdown = Player::GUIDropdown_t::allDropDowns[itr->name.GetString()]; | |||
| 23134 | dropdown.internalName = itr->name.GetString(); | |||
| 23135 | if ( itr->value.HasMember("title") ) | |||
| 23136 | { | |||
| 23137 | dropdown.title = itr->value["title"].GetString(); | |||
| 23138 | } | |||
| 23139 | else | |||
| 23140 | { | |||
| 23141 | dropdown.title = Language::get(4040); // "interact" | |||
| 23142 | } | |||
| 23143 | if ( itr->value.HasMember("align_right") ) | |||
| 23144 | { | |||
| 23145 | dropdown.alignRight = itr->value["align_right"].GetBool(); | |||
| 23146 | } | |||
| 23147 | if ( itr->value.HasMember("gui_module") ) | |||
| 23148 | { | |||
| 23149 | std::string moduleName = itr->value["gui_module"].GetString(); | |||
| 23150 | if ( moduleName == "character_sheet" ) | |||
| 23151 | { | |||
| 23152 | dropdown.module = Player::GUI_t::MODULE_CHARACTERSHEET; | |||
| 23153 | } | |||
| 23154 | else if ( moduleName == "inventory" ) | |||
| 23155 | { | |||
| 23156 | dropdown.module = Player::GUI_t::MODULE_INVENTORY; | |||
| 23157 | } | |||
| 23158 | else if ( moduleName == "chest" ) | |||
| 23159 | { | |||
| 23160 | dropdown.module = Player::GUI_t::MODULE_CHEST; | |||
| 23161 | } | |||
| 23162 | else if ( moduleName == "spells" ) | |||
| 23163 | { | |||
| 23164 | dropdown.module = Player::GUI_t::MODULE_SPELLS; | |||
| 23165 | } | |||
| 23166 | else if ( moduleName == "hotbar" ) | |||
| 23167 | { | |||
| 23168 | dropdown.module = Player::GUI_t::MODULE_HOTBAR; | |||
| 23169 | } | |||
| 23170 | else | |||
| 23171 | { | |||
| 23172 | dropdown.module = Player::GUI_t::MODULE_NONE; | |||
| 23173 | } | |||
| 23174 | } | |||
| 23175 | if ( itr->value.HasMember("default_option") ) | |||
| 23176 | { | |||
| 23177 | dropdown.defaultOption = itr->value["default_option"].GetInt(); | |||
| 23178 | } | |||
| 23179 | else | |||
| 23180 | { | |||
| 23181 | dropdown.defaultOption = 0; | |||
| 23182 | } | |||
| 23183 | for ( rapidjson::Value::ConstValueIterator options_itr = itr->value["options"].Begin(); | |||
| 23184 | options_itr != itr->value["options"].End(); ++options_itr ) | |||
| 23185 | { | |||
| 23186 | std::string text = ""; | |||
| 23187 | std::string controller_glyph = ""; | |||
| 23188 | std::string keyboard_glyph = ""; | |||
| 23189 | std::string action = "no_action"; | |||
| 23190 | if ( options_itr->HasMember("text") ) | |||
| 23191 | { | |||
| 23192 | text = (*options_itr)["text"].GetString(); | |||
| 23193 | } | |||
| 23194 | if ( options_itr->HasMember("controller_glyph") ) | |||
| 23195 | { | |||
| 23196 | controller_glyph = (*options_itr)["controller_glyph"].GetString(); | |||
| 23197 | } | |||
| 23198 | if ( options_itr->HasMember("keyboard_glyph") ) | |||
| 23199 | { | |||
| 23200 | keyboard_glyph = (*options_itr)["keyboard_glyph"].GetString(); | |||
| 23201 | } | |||
| 23202 | if ( options_itr->HasMember("action") ) | |||
| 23203 | { | |||
| 23204 | action = (*options_itr)["action"].GetString(); | |||
| 23205 | } | |||
| 23206 | dropdown.options.push_back(Player::GUIDropdown_t::DropdownOption_t(text, keyboard_glyph, controller_glyph, action)); | |||
| 23207 | } | |||
| 23208 | } | |||
| 23209 | } | |||
| 23210 | if ( d.HasMember("ping_status") ) | |||
| 23211 | { | |||
| 23212 | PingNetworkStatus_t::bEnabled = d["ping_status"]["enabled"].GetBool(); | |||
| 23213 | ||||
| 23214 | PingNetworkStatus_t::pingLimitGreen = d["ping_status"]["limit_green"].GetInt(); | |||
| 23215 | PingNetworkStatus_t::pingLimitYellow = d["ping_status"]["limit_yellow"].GetInt(); | |||
| 23216 | PingNetworkStatus_t::pingLimitOrange = d["ping_status"]["limit_orange"].GetInt(); | |||
| 23217 | ||||
| 23218 | PingNetworkStatus_t::pingHUDDisplayGreen = d["ping_status"]["show_green_always"].GetBool(); | |||
| 23219 | PingNetworkStatus_t::pingHUDDisplayYellow = d["ping_status"]["show_yellow_always"].GetBool(); | |||
| 23220 | PingNetworkStatus_t::pingHUDDisplayOrange = d["ping_status"]["show_orange_always"].GetBool(); | |||
| 23221 | PingNetworkStatus_t::pingHUDDisplayRed = d["ping_status"]["show_red_always"].GetBool(); | |||
| 23222 | PingNetworkStatus_t::pingHUDShowOKBriefly = d["ping_status"]["show_green_yellow_briefly"].GetBool(); | |||
| 23223 | PingNetworkStatus_t::pingHUDShowNumericValue = d["ping_status"]["show_numeric_on_hud"].GetBool(); | |||
| 23224 | } | |||
| 23225 | printlog("[JSON]: Successfully read json file %s", inputPath.c_str()); | |||
| 23226 | } | |||
| 23227 | } | |||
| 23228 | } | |||
| 23229 | } | |||
| 23230 | ||||
| 23231 | const int kSpellListHeight = 294; | |||
| 23232 | const int kSpellListGridY = 2; | |||
| 23233 | void createPlayerSpellList(const int player) | |||
| 23234 | { | |||
| 23235 | if ( !gui ) | |||
| 23236 | { | |||
| 23237 | return; | |||
| 23238 | } | |||
| 23239 | ||||
| 23240 | if ( players[player]->inventoryUI.spellFrame || !players[player]->inventoryUI.frame ) | |||
| 23241 | { | |||
| 23242 | return; | |||
| 23243 | } | |||
| 23244 | ||||
| 23245 | Frame* frame = players[player]->inventoryUI.frame->addFrame("player spells"); | |||
| 23246 | players[player]->inventoryUI.spellFrame = frame; | |||
| 23247 | frame->setSize(SDL_Rect{ 0, | |||
| 23248 | 0, | |||
| 23249 | 210, | |||
| 23250 | kSpellListHeight }); | |||
| 23251 | frame->setHollow(true); | |||
| 23252 | frame->setBorder(0); | |||
| 23253 | frame->setOwner(player); | |||
| 23254 | frame->setInheritParentFrameOpacity(false); | |||
| 23255 | ||||
| 23256 | SDL_Rect basePos{ 0, 0, 210, kSpellListHeight }; | |||
| 23257 | const int inventorySlotSize = players[player]->inventoryUI.getSlotSize(); | |||
| 23258 | ||||
| 23259 | players[player]->inventoryUI.spellSlotFrames.clear(); | |||
| 23260 | ||||
| 23261 | const int baseSlotOffsetX = 18; | |||
| 23262 | const int baseSlotOffsetY = 36; | |||
| 23263 | const int baseGridOffsetY = kSpellListGridY; | |||
| 23264 | ||||
| 23265 | SDL_Rect invSlotsPos{ basePos.x + 4, basePos.y + 4, basePos.w, 242 }; | |||
| 23266 | { | |||
| 23267 | int numGrids = (players[player]->inventoryUI.MAX_SPELLS_Y / players[player]->inventoryUI.spellPanel.kNumSpellsToDisplayVertical) + 1; | |||
| 23268 | ||||
| 23269 | const auto spellSlotsFrame = frame->addFrame("spell slots"); | |||
| 23270 | spellSlotsFrame->setSize(invSlotsPos); | |||
| 23271 | spellSlotsFrame->setActualSize(SDL_Rect{ 0, 0, basePos.w, 242 * numGrids }); | |||
| 23272 | spellSlotsFrame->setHollow(true); | |||
| 23273 | spellSlotsFrame->setAllowScrollBinds(false); | |||
| 23274 | ||||
| 23275 | auto gridImg = spellSlotsFrame->addImage(SDL_Rect{ baseSlotOffsetX, baseGridOffsetY, 162, 242 * numGrids }, | |||
| 23276 | 0xFFFFFFFF, "*images/ui/Inventory/HUD_Magic_ScrollGrid.png", "grid img"); | |||
| 23277 | gridImg->tiled = true; | |||
| 23278 | ||||
| 23279 | SDL_Rect currentSlotPos{ baseSlotOffsetX, baseSlotOffsetY, inventorySlotSize, inventorySlotSize }; | |||
| 23280 | const int maxSpellsX = Player::Inventory_t::MAX_SPELLS_X; | |||
| 23281 | const int maxSpellsY = Player::Inventory_t::MAX_SPELLS_Y; | |||
| 23282 | ||||
| 23283 | for ( int x = 0; x < maxSpellsX; ++x ) | |||
| 23284 | { | |||
| 23285 | currentSlotPos.x = baseSlotOffsetX + (x * inventorySlotSize); | |||
| 23286 | for ( int y = 0; y < maxSpellsY; ++y ) | |||
| 23287 | { | |||
| 23288 | currentSlotPos.y = baseSlotOffsetY + (y * inventorySlotSize); | |||
| 23289 | ||||
| 23290 | char slotname[32] = ""; | |||
| 23291 | snprintf(slotname, sizeof(slotname), "spell %d %d", x, y); | |||
| 23292 | ||||
| 23293 | auto slotFrame = spellSlotsFrame->addFrame(slotname); | |||
| 23294 | players[player]->inventoryUI.spellSlotFrames[x + y * 100] = slotFrame; | |||
| 23295 | SDL_Rect slotPos{ currentSlotPos.x, currentSlotPos.y, inventorySlotSize, inventorySlotSize }; | |||
| 23296 | slotFrame->setSize(slotPos); | |||
| 23297 | ||||
| 23298 | createPlayerInventorySlotFrameElements(slotFrame); | |||
| 23299 | } | |||
| 23300 | } | |||
| 23301 | } | |||
| 23302 | ||||
| 23303 | { | |||
| 23304 | auto bgFrame = frame->addFrame("spell base"); | |||
| 23305 | bgFrame->setSize(basePos); | |||
| 23306 | bgFrame->setHollow(true); | |||
| 23307 | const auto bgSize = bgFrame->getSize(); | |||
| 23308 | auto bg = bgFrame->addImage(SDL_Rect{ 0, 0, 210, kSpellListHeight }, | |||
| 23309 | makeColor(255, 255, 255, 255), | |||
| 23310 | "*#images/ui/Inventory/HUD_Magic_Base.png", "spell base img"); | |||
| 23311 | playerInventoryFrames[player].spellBaseImg = bg; | |||
| 23312 | ||||
| 23313 | auto slider = bgFrame->addSlider("spell slider"); | |||
| 23314 | slider->setBorder(16); | |||
| 23315 | slider->setMinValue(0); | |||
| 23316 | slider->setMaxValue(100); | |||
| 23317 | slider->setValue(0); | |||
| 23318 | SDL_Rect sliderPos{ basePos.w - 26, 50, 20, 192 }; | |||
| 23319 | slider->setRailSize(sliderPos); | |||
| 23320 | slider->setHandleSize(SDL_Rect{ 0, 0, 20, 28 }); | |||
| 23321 | slider->setOrientation(Slider::SLIDER_VERTICAL); | |||
| 23322 | //slider->setCallback(callback); | |||
| 23323 | slider->setColor(makeColor(255, 255, 255, 255)); | |||
| 23324 | slider->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 23325 | slider->setHandleImage("*#images/ui/Sliders/HUD_Magic_Slider_Emerald_01.png"); | |||
| 23326 | slider->setRailImage("*#images/ui/Sliders/HUD_Slider_Blank.png"); | |||
| 23327 | slider->setHideGlyphs(true); | |||
| 23328 | slider->setHideKeyboardGlyphs(true); | |||
| 23329 | slider->setHideSelectors(true); | |||
| 23330 | slider->setMenuConfirmControlType(0); | |||
| 23331 | ||||
| 23332 | auto sliderCapTop = bgFrame->addImage(SDL_Rect{ sliderPos.x + 2, sliderPos.y, 16, 16 }, | |||
| 23333 | makeColor(255, 255, 255, 255), | |||
| 23334 | "*#images/ui/Sliders/HUD_Magic_Slider_SettingTop_01.png", "spell slider top"); | |||
| 23335 | sliderCapTop->ontop = true; | |||
| 23336 | auto sliderCapBot = bgFrame->addImage(SDL_Rect{ sliderPos.x + 2, sliderPos.y + sliderPos.h - 16, 16, 16 }, | |||
| 23337 | makeColor(255, 255, 255, 255), | |||
| 23338 | "*#images/ui/Sliders/HUD_Magic_Slider_SettingBot_01.png", "spell slider bot"); | |||
| 23339 | sliderCapBot->ontop = true; | |||
| 23340 | ||||
| 23341 | const char* font = "fonts/pixel_maz.ttf#32#2"; | |||
| 23342 | auto titleText = bgFrame->addField("title txt", 64); | |||
| 23343 | titleText->setFont(font); | |||
| 23344 | titleText->setText(Language::get(5958)); | |||
| 23345 | titleText->setHJustify(Field::justify_t::CENTER); | |||
| 23346 | titleText->setVJustify(Field::justify_t::TOP); | |||
| 23347 | titleText->setSize(SDL_Rect{ 56, 12, 96, 24 }); | |||
| 23348 | titleText->setColor(makeColor(236, 175, 28, 255)); | |||
| 23349 | ||||
| 23350 | auto closeBtn = bgFrame->addButton("close spell button"); | |||
| 23351 | SDL_Rect closeBtnPos; | |||
| 23352 | closeBtnPos.x = 180; | |||
| 23353 | closeBtnPos.y = 6; | |||
| 23354 | closeBtnPos.w = 26; | |||
| 23355 | closeBtnPos.h = 26; | |||
| 23356 | closeBtn->setSize(closeBtnPos); | |||
| 23357 | closeBtn->setColor(makeColor(255, 255, 255, 255)); | |||
| 23358 | closeBtn->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 23359 | closeBtn->setTextHighlightColor(makeColor(201, 162, 100, 255)); | |||
| 23360 | closeBtn->setText("X"); | |||
| 23361 | closeBtn->setFont(font); | |||
| 23362 | closeBtn->setHideGlyphs(true); | |||
| 23363 | closeBtn->setHideKeyboardGlyphs(true); | |||
| 23364 | closeBtn->setHideSelectors(true); | |||
| 23365 | closeBtn->setMenuConfirmControlType(0); | |||
| 23366 | closeBtn->setBackground("*#images/ui/Inventory/chests/Button_X_00.png"); | |||
| 23367 | closeBtn->setBackgroundHighlighted("*#images/ui/Inventory/chests/Button_XHigh_00.png"); | |||
| 23368 | closeBtn->setBackgroundActivated("*#images/ui/Inventory/chests/Button_XPress_00.png"); | |||
| 23369 | closeBtn->setCallback([](Button& button) { | |||
| 23370 | if ( players[button.getOwner()]->inventory_mode == INVENTORY_MODE_SPELL ) | |||
| 23371 | { | |||
| 23372 | players[button.getOwner()]->inventoryUI.cycleInventoryTab(); | |||
| 23373 | } | |||
| 23374 | players[button.getOwner()]->inventoryUI.spellPanel.closeSpellPanel(); | |||
| 23375 | }); | |||
| 23376 | closeBtn->setTickCallback([](Widget& widget) { | |||
| 23377 | if ( widget.isSelected() ) | |||
| 23378 | { | |||
| 23379 | if ( !inputs.getVirtualMouse(widget.getOwner())->draw_cursor ) | |||
| 23380 | { | |||
| 23381 | widget.deselect(); | |||
| 23382 | } | |||
| 23383 | } | |||
| 23384 | }); | |||
| 23385 | ||||
| 23386 | auto skillBg = bgFrame->addImage(SDL_Rect{ 6, 6, 32, 32 }, | |||
| 23387 | makeColor(255, 255, 255, 255), | |||
| 23388 | "*#images/ui/Inventory/HUD_Magic_Casting_BG_01.png", "spell skill bg"); | |||
| 23389 | ||||
| 23390 | auto skillIcon = bgFrame->addImage(SDL_Rect{ skillBg->pos.x + 4, skillBg->pos.y + 4, 24, 24 }, | |||
| 23391 | makeColor(255, 255, 255, 255), | |||
| 23392 | "", "spell skill icon"); | |||
| 23393 | ||||
| 23394 | auto closeGlyph = bgFrame->addImage(SDL_Rect{ 0, 0, 24, 24 }, | |||
| 23395 | makeColor(255, 255, 255, 255), | |||
| 23396 | "", "close spell glyph"); | |||
| 23397 | closeGlyph->disabled = true; | |||
| 23398 | } | |||
| 23399 | } | |||
| 23400 | ||||
| 23401 | void closeChestGUIAction(const int player) | |||
| 23402 | { | |||
| 23403 | players[player]->hud.compactLayoutMode = Player::HUD_t::COMPACT_LAYOUT_INVENTORY; | |||
| 23404 | //players[player]->inventory_mode = INVENTORY_MODE_ITEM; | |||
| 23405 | if ( players[player]->GUI.activeModule != Player::GUI_t::MODULE_INVENTORY ) | |||
| 23406 | { | |||
| 23407 | players[player]->GUI.activateModule(Player::GUI_t::MODULE_INVENTORY); | |||
| 23408 | if ( !inputs.getVirtualMouse(player)->draw_cursor ) | |||
| 23409 | { | |||
| 23410 | players[player]->GUI.warpControllerToModule(false); | |||
| 23411 | } | |||
| 23412 | } | |||
| 23413 | if ( openedChest[player] ) | |||
| 23414 | { | |||
| 23415 | openedChest[player]->closeChest(); | |||
| 23416 | } | |||
| 23417 | else | |||
| 23418 | { | |||
| 23419 | players[player]->inventoryUI.chestGUI.closeChest(); | |||
| 23420 | } | |||
| 23421 | } | |||
| 23422 | ||||
| 23423 | bool takeAllChestGUIAction(const int player) | |||
| 23424 | { | |||
| 23425 | if ( !openedChest[player] ) | |||
| 23426 | { | |||
| 23427 | return false; | |||
| 23428 | } | |||
| 23429 | ||||
| 23430 | list_t* chest_inventory = nullptr; | |||
| 23431 | if ( multiplayer == CLIENT2 ) | |||
| 23432 | { | |||
| 23433 | chest_inventory = &chestInv[player]; | |||
| 23434 | } | |||
| 23435 | else if ( openedChest[player]->children.first && openedChest[player]->children.first->element ) | |||
| 23436 | { | |||
| 23437 | chest_inventory = (list_t*)openedChest[player]->children.first->element; | |||
| 23438 | } | |||
| 23439 | if ( !chest_inventory ) | |||
| 23440 | { | |||
| 23441 | // no chest inventory available | |||
| 23442 | return false; | |||
| 23443 | } | |||
| 23444 | ||||
| 23445 | std::vector<std::pair<int, Item*>> chestSlotOrder; | |||
| 23446 | for ( node_t* node = chest_inventory->first; node != nullptr; node = node->next ) | |||
| 23447 | { | |||
| 23448 | Item* item2 = static_cast<Item*>(node->element); | |||
| 23449 | if ( item2 ) | |||
| 23450 | { | |||
| 23451 | int key = item2->x + item2->y * 100; | |||
| 23452 | chestSlotOrder.push_back(std::make_pair(key, item2)); | |||
| 23453 | } | |||
| 23454 | } | |||
| 23455 | int numItems = (int)chestSlotOrder.size(); | |||
| 23456 | std::sort(chestSlotOrder.begin(), chestSlotOrder.end()); // sort ascending by position, left to right, then down | |||
| 23457 | int pickedUpItems = 0; | |||
| 23458 | for ( auto& keyValue : chestSlotOrder ) | |||
| 23459 | { | |||
| 23460 | Item* item = keyValue.second; | |||
| 23461 | bool tryAddToInventory = true; | |||
| 23462 | int loops = 0; | |||
| 23463 | while ( tryAddToInventory ) | |||
| 23464 | { | |||
| 23465 | ++loops; | |||
| 23466 | if ( item->count <= 0 ) | |||
| 23467 | { | |||
| 23468 | break; | |||
| 23469 | } | |||
| 23470 | int oldItemQty = 0; | |||
| 23471 | int destItemQty = 0; | |||
| 23472 | bool oldIdentify = item->identified; | |||
| 23473 | if ( skillCapstoneUnlocked(player, PRO_APPRAISAL) ) | |||
| 23474 | { | |||
| 23475 | item->identified = true; | |||
| 23476 | } | |||
| 23477 | auto result = getItemStackingBehavior(player, item, nullptr, oldItemQty, destItemQty); | |||
| 23478 | item->identified = oldIdentify; | |||
| 23479 | int amountToPlace = item->count - oldItemQty; | |||
| 23480 | assert(amountToPlace > 0)(static_cast<void> (0)); | |||
| 23481 | if ( amountToPlace <= 0 ) | |||
| 23482 | { | |||
| 23483 | break; | |||
| 23484 | } | |||
| 23485 | switch ( result.resultType ) | |||
| 23486 | { | |||
| 23487 | case ITEM_ADDED_PARTIALLY_TO_DESTINATION_STACK: | |||
| 23488 | { | |||
| 23489 | if ( Item* inventoryItem = takeItemFromChest(player, item, amountToPlace, result.itemToStackInto, false, false) ) | |||
| 23490 | { | |||
| 23491 | // need to do another place operation. | |||
| 23492 | } | |||
| 23493 | else | |||
| 23494 | { | |||
| 23495 | tryAddToInventory = false; | |||
| 23496 | } | |||
| 23497 | if ( loops == 1 ) | |||
| 23498 | { | |||
| 23499 | ++pickedUpItems; | |||
| 23500 | } | |||
| 23501 | break; | |||
| 23502 | } | |||
| 23503 | case ITEM_ADDED_ENTIRELY_TO_DESTINATION_STACK: | |||
| 23504 | { | |||
| 23505 | // operation success, can finish here. | |||
| 23506 | Item* inventoryItem = takeItemFromChest(player, item, amountToPlace, result.itemToStackInto, false, false); | |||
| 23507 | tryAddToInventory = false; | |||
| 23508 | if ( loops == 1 ) | |||
| 23509 | { | |||
| 23510 | ++pickedUpItems; | |||
| 23511 | } | |||
| 23512 | break; | |||
| 23513 | } | |||
| 23514 | case ITEM_ADDED_WITHOUT_NEEDING_STACK: | |||
| 23515 | { | |||
| 23516 | // check for inventory space | |||
| 23517 | if ( !players[player]->inventoryUI.bItemInventoryHasFreeSlot() ) | |||
| 23518 | { | |||
| 23519 | // no space | |||
| 23520 | tryAddToInventory = false; | |||
| 23521 | break; | |||
| 23522 | } | |||
| 23523 | Item* inventoryItem = takeItemFromChest(player, item, amountToPlace, nullptr, true, false); | |||
| 23524 | if ( oldItemQty > 0 ) | |||
| 23525 | { | |||
| 23526 | // more work to do (unusually large stacks exceeding normal limits) | |||
| 23527 | } | |||
| 23528 | else | |||
| 23529 | { | |||
| 23530 | tryAddToInventory = false; | |||
| 23531 | } | |||
| 23532 | if ( loops == 1 ) | |||
| 23533 | { | |||
| 23534 | ++pickedUpItems; | |||
| 23535 | } | |||
| 23536 | break; | |||
| 23537 | } | |||
| 23538 | default: | |||
| 23539 | // error out | |||
| 23540 | tryAddToInventory = false; | |||
| 23541 | break; | |||
| 23542 | } | |||
| 23543 | } | |||
| 23544 | } | |||
| 23545 | ||||
| 23546 | if ( pickedUpItems > 0 ) | |||
| 23547 | { | |||
| 23548 | messagePlayer(player, MESSAGE_INVENTORY, Language::get(4099), pickedUpItems); | |||
| 23549 | playSound(35 + local_rng.rand() % 3, 64); | |||
| 23550 | } | |||
| 23551 | else if ( pickedUpItems == 0 && numItems > 0 ) | |||
| 23552 | { | |||
| 23553 | messagePlayer(player, MESSAGE_INVENTORY, Language::get(4100)); | |||
| 23554 | playSoundPlayer(player, 90, 64); | |||
| 23555 | } | |||
| 23556 | ||||
| 23557 | return true; | |||
| 23558 | } | |||
| 23559 | ||||
| 23560 | const int chestBaseImgBorderWidth = 16; | |||
| 23561 | const int chestBaseImgBorderTopHeight = 20; | |||
| 23562 | PlayerInventoryFrames_t playerInventoryFrames[MAXPLAYERS4]; | |||
| 23563 | ||||
| 23564 | void createChestGUI(const int player) | |||
| 23565 | { | |||
| 23566 | if ( !gui ) | |||
| 23567 | { | |||
| 23568 | return; | |||
| 23569 | } | |||
| 23570 | ||||
| 23571 | if ( players[player]->inventoryUI.chestFrame || !players[player]->inventoryUI.frame ) | |||
| 23572 | { | |||
| 23573 | return; | |||
| 23574 | } | |||
| 23575 | ||||
| 23576 | Frame* frame = players[player]->inventoryUI.frame->addFrame("chest"); | |||
| 23577 | players[player]->inventoryUI.chestFrame = frame; | |||
| 23578 | ||||
| 23579 | frame->setSize(SDL_Rect{ 0, | |||
| 23580 | 0, | |||
| 23581 | 194, | |||
| 23582 | 250 }); | |||
| 23583 | frame->setHollow(true); | |||
| 23584 | frame->setBorder(0); | |||
| 23585 | frame->setOwner(player); | |||
| 23586 | frame->setInheritParentFrameOpacity(false); | |||
| 23587 | ||||
| 23588 | SDL_Rect basePos{ 0, 0, 194, 130 }; | |||
| 23589 | { | |||
| 23590 | auto bgFrame = frame->addFrame("chest base"); | |||
| 23591 | playerInventoryFrames[player].chestBgFrame = bgFrame; | |||
| 23592 | bgFrame->setSize(basePos); | |||
| 23593 | bgFrame->setHollow(false); | |||
| 23594 | const auto bgSize = bgFrame->getSize(); | |||
| 23595 | auto bg = bgFrame->addImage(SDL_Rect{ 6, 0, 182, 172 }, | |||
| 23596 | makeColor( 255, 255, 255, 255), | |||
| 23597 | "*#images/ui/Inventory/chests/Chest_Main_00.png", "chest base img"); | |||
| 23598 | playerInventoryFrames[player].chestBaseImg = bg; | |||
| 23599 | auto bg2 = bgFrame->addImage(SDL_Rect{ 0, 0, 194, 66 }, | |||
| 23600 | makeColor( 255, 255, 255, 255), | |||
| 23601 | "*#images/ui/Inventory/chests/Chest_Top_00.png", "chest lid img"); | |||
| 23602 | //bg->disabled = false; | |||
| 23603 | ||||
| 23604 | //auto slider = bgFrame->addSlider("chest slider"); | |||
| 23605 | //slider->setBorder(24); | |||
| 23606 | //slider->setMinValue(0); | |||
| 23607 | //slider->setMaxValue(100); | |||
| 23608 | //slider->setValue(0); | |||
| 23609 | //SDL_Rect sliderPos{ basePos.w - 38, 8, 30, 234 }; | |||
| 23610 | //slider->setRailSize(sliderPos); | |||
| 23611 | //slider->setHandleSize(SDL_Rect{ 0, 0, 34, 34 }); | |||
| 23612 | //slider->setOrientation(Slider::SLIDER_VERTICAL); | |||
| 23613 | ////slider->setCallback(callback); | |||
| 23614 | //slider->setColor(makeColor(255, 255, 255, 255)); | |||
| 23615 | //slider->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 23616 | //slider->setHandleImage("*#images/ui/Main Menus/Settings/Settings_Slider_Boulder00.png"); | |||
| 23617 | //slider->setRailImage("*#images/ui/Main Menus/Settings/Settings_Slider_Backing00.png"); | |||
| 23618 | //slider->setHideGlyphs(true); | |||
| 23619 | //slider->setHideKeyboardGlyphs(true); | |||
| 23620 | //slider->setHideSelectors(true); | |||
| 23621 | //slider->setMenuConfirmControlType(0); | |||
| 23622 | ||||
| 23623 | const char* font = "fonts/pixel_maz.ttf#32#2"; | |||
| 23624 | auto titleText = bgFrame->addField("title txt", 64); | |||
| 23625 | titleText->setFont(font); | |||
| 23626 | titleText->setText(Language::get(5959)); | |||
| 23627 | titleText->setHJustify(Field::justify_t::CENTER); | |||
| 23628 | titleText->setVJustify(Field::justify_t::CENTER); | |||
| 23629 | titleText->setSize(SDL_Rect{ basePos.x + 4, 0, 162, 32 }); | |||
| 23630 | titleText->setColor(makeColor(188, 154, 114, 255)); | |||
| 23631 | ||||
| 23632 | auto closeBtn = bgFrame->addButton("close chest button"); | |||
| 23633 | SDL_Rect closeBtnPos = titleText->getSize(); | |||
| 23634 | closeBtnPos.x = closeBtnPos.x + closeBtnPos.w - 98; | |||
| 23635 | closeBtnPos.w = 26; | |||
| 23636 | closeBtnPos.h = 26; | |||
| 23637 | closeBtn->setSize(closeBtnPos); | |||
| 23638 | closeBtn->setColor(makeColor(255, 255, 255, 255)); | |||
| 23639 | closeBtn->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 23640 | closeBtn->setText("X"); | |||
| 23641 | closeBtn->setFont(font); | |||
| 23642 | closeBtn->setHideGlyphs(true); | |||
| 23643 | closeBtn->setHideKeyboardGlyphs(true); | |||
| 23644 | closeBtn->setHideSelectors(true); | |||
| 23645 | closeBtn->setMenuConfirmControlType(0); | |||
| 23646 | closeBtn->setBackground("*#images/ui/Inventory/chests/Button_X_00.png"); | |||
| 23647 | closeBtn->setBackgroundHighlighted("*#images/ui/Inventory/chests/Button_XHigh_00.png"); | |||
| 23648 | closeBtn->setBackgroundActivated("*#images/ui/Inventory/chests/Button_XPress_00.png"); | |||
| 23649 | closeBtn->setTextHighlightColor(makeColor(201, 162, 100, 255)); | |||
| 23650 | closeBtn->setCallback([](Button& button) { | |||
| 23651 | closeChestGUIAction(button.getOwner()); | |||
| 23652 | }); | |||
| 23653 | ||||
| 23654 | auto grabAllBtn = bgFrame->addButton("grab all button"); | |||
| 23655 | SDL_Rect grabBtnPos = titleText->getSize(); | |||
| 23656 | grabBtnPos.x = closeBtnPos.x + closeBtnPos.w - 86; | |||
| 23657 | grabBtnPos.w = 86; | |||
| 23658 | grabBtnPos.h = 26; | |||
| 23659 | grabAllBtn->setSize(grabBtnPos); | |||
| 23660 | grabAllBtn->setColor(makeColor(255, 255, 255, 255)); | |||
| 23661 | grabAllBtn->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 23662 | grabAllBtn->setText(Language::get(5960)); | |||
| 23663 | grabAllBtn->setFont(font); | |||
| 23664 | grabAllBtn->setHideGlyphs(true); | |||
| 23665 | grabAllBtn->setHideKeyboardGlyphs(true); | |||
| 23666 | grabAllBtn->setHideSelectors(true); | |||
| 23667 | grabAllBtn->setMenuConfirmControlType(0); | |||
| 23668 | grabAllBtn->setBackground("*#images/ui/Inventory/chests/Button_TakeAll_00.png"); | |||
| 23669 | grabAllBtn->setBackgroundHighlighted("*#images/ui/Inventory/chests/Button_TakeAllHigh_00.png"); | |||
| 23670 | grabAllBtn->setBackgroundActivated("*#images/ui/Inventory/chests/Button_TakeAllPress_00.png"); | |||
| 23671 | grabAllBtn->setTextHighlightColor(makeColor(201, 162, 100, 255)); | |||
| 23672 | grabAllBtn->setCallback([](Button& button) { | |||
| 23673 | takeAllChestGUIAction(button.getOwner()); | |||
| 23674 | Player::soundActivate(); | |||
| 23675 | }); | |||
| 23676 | ||||
| 23677 | std::string promptFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 23678 | const int promptWidth = 60; | |||
| 23679 | const int promptHeight = 27; | |||
| 23680 | auto promptBack = bgFrame->addField("prompt back txt", 16); | |||
| 23681 | promptBack->setSize(SDL_Rect{ 0, 0, promptWidth, promptHeight }); | |||
| 23682 | promptBack->setFont(promptFont.c_str()); | |||
| 23683 | promptBack->setHJustify(Field::justify_t::RIGHT); | |||
| 23684 | promptBack->setVJustify(Field::justify_t::CENTER); | |||
| 23685 | promptBack->setText(Language::get(4053)); | |||
| 23686 | //promptBack->setOntop(true); | |||
| 23687 | promptBack->setColor(makeColor(201, 162, 100, 255)); | |||
| 23688 | ||||
| 23689 | auto promptBackImg = bgFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, | |||
| 23690 | "", "prompt back img"); | |||
| 23691 | promptBackImg->disabled = true; | |||
| 23692 | ||||
| 23693 | auto promptGrabAll = bgFrame->addField("prompt grab txt", 16); | |||
| 23694 | promptGrabAll->setSize(SDL_Rect{ 0, 0, promptWidth, promptHeight }); | |||
| 23695 | promptGrabAll->setFont(promptFont.c_str()); | |||
| 23696 | promptGrabAll->setHJustify(Field::justify_t::RIGHT); | |||
| 23697 | promptGrabAll->setVJustify(Field::justify_t::CENTER); | |||
| 23698 | promptGrabAll->setText(Language::get(4091)); | |||
| 23699 | //promptBack->setOntop(true); | |||
| 23700 | promptGrabAll->setColor(makeColor(201, 162, 100, 255)); | |||
| 23701 | ||||
| 23702 | auto promptGrabImg = bgFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, | |||
| 23703 | "", "prompt grab img"); | |||
| 23704 | promptBackImg->disabled = true; | |||
| 23705 | } | |||
| 23706 | ||||
| 23707 | const int inventorySlotSize = players[player]->inventoryUI.getSlotSize(); | |||
| 23708 | ||||
| 23709 | players[player]->inventoryUI.chestSlotFrames.clear(); | |||
| 23710 | ||||
| 23711 | const int baseSlotOffsetX = 0; | |||
| 23712 | const int baseSlotOffsetY = 0; | |||
| 23713 | ||||
| 23714 | const int gridHeight = 120 + 2; // 120px is grid img, plus 2px to tile the image for bottom border. | |||
| 23715 | SDL_Rect invSlotsPos{ basePos.x + chestBaseImgBorderWidth, basePos.y + 4 + chestBaseImgBorderTopHeight, basePos.w, gridHeight }; | |||
| 23716 | { | |||
| 23717 | int numGrids = (players[player]->inventoryUI.MAX_CHEST_Y / players[player]->inventoryUI.chestGUI.kNumItemsToDisplayVertical) + 1; | |||
| 23718 | ||||
| 23719 | const auto chestSlotsFrame = frame->addFrame("chest slots"); | |||
| 23720 | chestSlotsFrame->setSize(invSlotsPos); | |||
| 23721 | chestSlotsFrame->setActualSize(SDL_Rect{ 0, 0, basePos.w, gridHeight * numGrids }); | |||
| 23722 | chestSlotsFrame->setHollow(true); | |||
| 23723 | chestSlotsFrame->setAllowScrollBinds(false); | |||
| 23724 | playerInventoryFrames[player].chestFrameSlots = chestSlotsFrame; | |||
| 23725 | ||||
| 23726 | auto gridImg = chestSlotsFrame->addImage(SDL_Rect{ baseSlotOffsetX, baseSlotOffsetY, 162, gridHeight * numGrids }, | |||
| 23727 | makeColor(255, 255, 255, 32), "*#images/ui/Inventory/HUD_Chest4x3_ScrollGrid.png", "grid img"); | |||
| 23728 | gridImg->tiled = true; | |||
| 23729 | ||||
| 23730 | SDL_Rect currentSlotPos{ baseSlotOffsetX, baseSlotOffsetY, inventorySlotSize, inventorySlotSize }; | |||
| 23731 | const int maxChestX = Player::Inventory_t::MAX_CHEST_X; | |||
| 23732 | const int maxChestY = Player::Inventory_t::MAX_CHEST_Y; | |||
| 23733 | ||||
| 23734 | for ( int x = 0; x < maxChestX; ++x ) | |||
| 23735 | { | |||
| 23736 | currentSlotPos.x = baseSlotOffsetX + (x * inventorySlotSize); | |||
| 23737 | for ( int y = 0; y < maxChestY; ++y ) | |||
| 23738 | { | |||
| 23739 | currentSlotPos.y = baseSlotOffsetY + (y * inventorySlotSize); | |||
| 23740 | ||||
| 23741 | char slotname[32] = ""; | |||
| 23742 | snprintf(slotname, sizeof(slotname), "chest %d %d", x, y); | |||
| 23743 | ||||
| 23744 | auto slotFrame = chestSlotsFrame->addFrame(slotname); | |||
| 23745 | players[player]->inventoryUI.chestSlotFrames[x + y * 100] = slotFrame; | |||
| 23746 | SDL_Rect slotPos{ currentSlotPos.x, currentSlotPos.y, inventorySlotSize, inventorySlotSize }; | |||
| 23747 | slotFrame->setSize(slotPos); | |||
| 23748 | ||||
| 23749 | createPlayerInventorySlotFrameElements(slotFrame); | |||
| 23750 | } | |||
| 23751 | } | |||
| 23752 | } | |||
| 23753 | } | |||
| 23754 | ||||
| 23755 | const int Player::ShopGUI_t::MAX_SHOP_X = 5; | |||
| 23756 | const int Player::ShopGUI_t::MAX_SHOP_Y = 5; | |||
| 23757 | ||||
| 23758 | void closeShopGUIAction(const int player) | |||
| 23759 | { | |||
| 23760 | players[player]->hud.compactLayoutMode = Player::HUD_t::COMPACT_LAYOUT_INVENTORY; | |||
| 23761 | if ( players[player]->GUI.activeModule != Player::GUI_t::MODULE_INVENTORY ) | |||
| 23762 | { | |||
| 23763 | players[player]->GUI.activateModule(Player::GUI_t::MODULE_INVENTORY); | |||
| 23764 | if ( !inputs.getVirtualMouse(player)->draw_cursor ) | |||
| 23765 | { | |||
| 23766 | players[player]->GUI.warpControllerToModule(false); | |||
| 23767 | } | |||
| 23768 | } | |||
| 23769 | if ( uidToEntity(shopkeeper[player]) ) | |||
| 23770 | { | |||
| 23771 | closeShop(player); | |||
| 23772 | } | |||
| 23773 | else | |||
| 23774 | { | |||
| 23775 | players[player]->shopGUI.closeShop(); | |||
| 23776 | } | |||
| 23777 | } | |||
| 23778 | ||||
| 23779 | void toggleShopBuybackView(const int player) | |||
| 23780 | { | |||
| 23781 | players[player]->shopGUI.buybackView = !players[player]->shopGUI.buybackView; | |||
| 23782 | } | |||
| 23783 | ||||
| 23784 | void createShopGUI(const int player) | |||
| 23785 | { | |||
| 23786 | if ( !gui ) | |||
| 23787 | { | |||
| 23788 | return; | |||
| 23789 | } | |||
| 23790 | ||||
| 23791 | auto& shopGUI = players[player]->shopGUI; | |||
| 23792 | ||||
| 23793 | if ( shopGUI.shopFrame || !players[player]->inventoryUI.frame ) | |||
| 23794 | { | |||
| 23795 | return; | |||
| 23796 | } | |||
| 23797 | ||||
| 23798 | SDL_Rect basePos{ 0, 0, 520, 334 }; | |||
| 23799 | ||||
| 23800 | Frame* frame = players[player]->inventoryUI.frame->addFrame("shop"); | |||
| 23801 | shopGUI.shopFrame = frame; | |||
| 23802 | frame->setSize(SDL_Rect{ players[player]->camera_virtualx1(), | |||
| 23803 | players[player]->camera_virtualy1(), | |||
| 23804 | basePos.w, | |||
| 23805 | basePos.h }); | |||
| 23806 | frame->setHollow(true); | |||
| 23807 | frame->setBorder(0); | |||
| 23808 | frame->setOwner(player); | |||
| 23809 | frame->setInheritParentFrameOpacity(false); | |||
| 23810 | ||||
| 23811 | { | |||
| 23812 | auto bgFrame = frame->addFrame("shop base"); | |||
| 23813 | bgFrame->setSize(basePos); | |||
| 23814 | bgFrame->setHollow(false); | |||
| 23815 | const auto bgSize = bgFrame->getSize(); | |||
| 23816 | auto bg = bgFrame->addImage(SDL_Rect{ 0, 0, basePos.w, basePos.h }, | |||
| 23817 | makeColor(255, 255, 255, 255), | |||
| 23818 | "*#images/ui/Shop/Shop_Window_03C.png", "shop base img"); | |||
| 23819 | auto bgGrid = bgFrame->addImage(SDL_Rect{ 12, 18, 206, 214 }, | |||
| 23820 | makeColor(255, 255, 255, 64), | |||
| 23821 | "*#images/ui/Shop/Shop_ItemSlots_Areas03.png", "shop grid img"); | |||
| 23822 | ||||
| 23823 | const char* font = "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 23824 | Uint32 titleColor = makeColor(219, 157, 20, 255); | |||
| 23825 | Uint32 titleOutline = makeColor(29, 16, 11, 255); | |||
| 23826 | auto titleText = bgFrame->addField("shop name", 64); | |||
| 23827 | titleText->setFont(font); | |||
| 23828 | titleText->setText(""); | |||
| 23829 | titleText->setHJustify(Field::justify_t::CENTER); | |||
| 23830 | titleText->setVJustify(Field::justify_t::TOP); | |||
| 23831 | titleText->setSize(SDL_Rect{ 228, 29, 184, 24 }); | |||
| 23832 | titleText->setTextColor(titleColor); | |||
| 23833 | titleText->setOutlineColor(titleOutline); | |||
| 23834 | ||||
| 23835 | const char* shoptypefont = "fonts/pixelmix.ttf#16#2"; | |||
| 23836 | auto shopTypeText = bgFrame->addField("shop type", 64); | |||
| 23837 | shopTypeText->setFont(shoptypefont); | |||
| 23838 | shopTypeText->setText(""); | |||
| 23839 | shopTypeText->setHJustify(Field::justify_t::CENTER); | |||
| 23840 | shopTypeText->setVJustify(Field::justify_t::TOP); | |||
| 23841 | shopTypeText->setSize(SDL_Rect{ 228, 48, 184, 82 }); | |||
| 23842 | shopTypeText->setTextColor(titleColor); | |||
| 23843 | shopTypeText->setOutlineColor(titleOutline); | |||
| 23844 | ||||
| 23845 | auto shopkeeperImg = bgFrame->addImage(SDL_Rect{ basePos.w - 14 - 80, 14, 80, 80 }, 0xFFFFFFFF, | |||
| 23846 | "*#images/ui/Shop/shopkeeper.png", "shopkeeper img"); | |||
| 23847 | ||||
| 23848 | auto closeBtn = bgFrame->addButton("close shop button"); | |||
| 23849 | SDL_Rect closeBtnPos{ basePos.w - 34, 8, 26, 26 }; | |||
| 23850 | closeBtn->setSize(closeBtnPos); | |||
| 23851 | closeBtn->setColor(makeColor(255, 255, 255, 255)); | |||
| 23852 | closeBtn->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 23853 | closeBtn->setText("X"); | |||
| 23854 | closeBtn->setFont(font); | |||
| 23855 | closeBtn->setHideGlyphs(true); | |||
| 23856 | closeBtn->setHideKeyboardGlyphs(true); | |||
| 23857 | closeBtn->setHideSelectors(true); | |||
| 23858 | closeBtn->setMenuConfirmControlType(0); | |||
| 23859 | closeBtn->setBackground("*#images/ui/Shop/Button_X_00.png"); | |||
| 23860 | closeBtn->setBackgroundHighlighted("*#images/ui/Shop/Button_XHigh_00.png"); | |||
| 23861 | closeBtn->setBackgroundActivated("*#images/ui/Shop/Button_XPress_00.png"); | |||
| 23862 | closeBtn->setTextHighlightColor(makeColor(201, 162, 100, 255)); | |||
| 23863 | closeBtn->setCallback([](Button& button) { | |||
| 23864 | closeShopGUIAction(button.getOwner()); | |||
| 23865 | Player::soundCancel(); | |||
| 23866 | }); | |||
| 23867 | ||||
| 23868 | auto discountFrame = bgFrame->addFrame("discount frame"); | |||
| 23869 | discountFrame->setHollow(true); | |||
| 23870 | discountFrame->setBorder(0); | |||
| 23871 | discountFrame->setSize(SDL_Rect{ bgFrame->getSize().w - 112, bgFrame->getSize().h - 124, 98, 24 }); | |||
| 23872 | discountFrame->setDisabled(false); | |||
| 23873 | ||||
| 23874 | auto chatWindow = bgFrame->addFrame("chatter"); | |||
| 23875 | auto tl = chatWindow->addImage(SDL_Rect{ 0, 0, 34, 34 }, 0xFFFFFFFF, | |||
| 23876 | "*#images/ui/Shop/Textbox_TLWings00.png", "top left img"); | |||
| 23877 | auto tm = chatWindow->addImage(SDL_Rect{ 0, 0, 2, 6 }, 0xFFFFFFFF, | |||
| 23878 | "*#images/ui/Shop/Textbox_WingsT_00.png", "top img"); | |||
| 23879 | auto tr = chatWindow->addImage(SDL_Rect{ 0, 0, 14, 28 }, 0xFFFFFFFF, | |||
| 23880 | "*#images/ui/Shop/Textbox_TR00.png", "top right img"); | |||
| 23881 | ||||
| 23882 | auto ml = chatWindow->addImage(SDL_Rect{ 0, 0, 6, 0 }, 0xFFFFFFFF, | |||
| 23883 | "*#images/ui/Shop/Textbox_WingsL_00.png", "middle left img"); | |||
| 23884 | auto mm1 = chatWindow->addImage(SDL_Rect{ 0, 0, 2, 2 }, 0xFFFFFFFF, | |||
| 23885 | "*#images/ui/Shop/Textbox_CenterColor_00.png", "middle 1 img"); | |||
| 23886 | auto mm2 = chatWindow->addImage(SDL_Rect{ 0, 0, 2, 2 }, 0xFFFFFFFF, | |||
| 23887 | "*#images/ui/Shop/Textbox_CenterColor_00.png", "middle 2 img"); | |||
| 23888 | auto mr = chatWindow->addImage(SDL_Rect{ 0, 0, 6, 0 }, 0xFFFFFFFF, | |||
| 23889 | "*#images/ui/Shop/Textbox_WingsR_00.png", "middle right img"); | |||
| 23890 | ||||
| 23891 | auto bl = chatWindow->addImage(SDL_Rect{ 0, 0, 28, 14 }, 0xFFFFFFFF, | |||
| 23892 | "*#images/ui/Shop/Textbox_BL00.png", "bottom left img"); | |||
| 23893 | auto bm = chatWindow->addImage(SDL_Rect{ 0, 0, 2, 6 }, 0xFFFFFFFF, | |||
| 23894 | "*#images/ui/Shop/Textbox_WingsB_00.png", "bottom img"); | |||
| 23895 | auto br = chatWindow->addImage(SDL_Rect{ 0, 0, 14, 14 }, 0xFFFFFFFF, | |||
| 23896 | "*#images/ui/Shop/Textbox_BR00.png", "bottom right img"); | |||
| 23897 | ||||
| 23898 | auto pointer = chatWindow->addImage(SDL_Rect{ 0, 0, 20, 22 }, 0xFFFFFFFF, | |||
| 23899 | "*#images/ui/Shop/Textbox_SpeakerPointer_TR01.png", "pointer img"); | |||
| 23900 | ||||
| 23901 | auto bodyFont = "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 23902 | auto chatText = chatWindow->addField("chat body", 1024); | |||
| 23903 | chatText->setFont(bodyFont); | |||
| 23904 | chatText->setText(""); | |||
| 23905 | chatText->setHJustify(Field::justify_t::TOP); | |||
| 23906 | chatText->setVJustify(Field::justify_t::LEFT); | |||
| 23907 | chatText->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 23908 | //chatText->setColor(makeColor(29, 16, 11, 255)); | |||
| 23909 | chatText->setTextColor(makeColor(29, 16, 11, 255)); | |||
| 23910 | chatText->setOutlineColor(makeColor(0, 0, 0, 1)); | |||
| 23911 | ||||
| 23912 | { | |||
| 23913 | auto valueFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 23914 | ||||
| 23915 | auto discountLabelText = bgFrame->addField("discount label", 32); | |||
| 23916 | discountLabelText->setFont(valueFont); | |||
| 23917 | discountLabelText->setText(Language::get(4122)); | |||
| 23918 | discountLabelText->setHJustify(Field::justify_t::RIGHT); | |||
| 23919 | discountLabelText->setVJustify(Field::justify_t::TOP); | |||
| 23920 | discountLabelText->setSize(SDL_Rect{ bgFrame->getSize().w - 106 - 180 - 12, bgFrame->getSize().h - 92 - 30, 180, 24 }); | |||
| 23921 | discountLabelText->setTextColor(makeColor(201, 162, 100, 255)); | |||
| 23922 | discountLabelText->setOutlineColor(makeColor(29, 16, 11, 255)); | |||
| 23923 | ||||
| 23924 | auto discountImg = discountFrame->addImage(SDL_Rect{ 0, 0, 98, 24 }, 0xFFFFFFFF, | |||
| 23925 | "*#images/ui/Shop/Shop_DiscountLabel_00.png", "discount img"); | |||
| 23926 | ||||
| 23927 | auto discountValue = discountFrame->addField("discount", 32); | |||
| 23928 | discountValue->setFont(valueFont); | |||
| 23929 | discountValue->setText(""); | |||
| 23930 | discountValue->setHJustify(Field::justify_t::RIGHT); | |||
| 23931 | discountValue->setVJustify(Field::justify_t::TOP); | |||
| 23932 | discountValue->setSize(SDL_Rect{ 14, 2, 80, 24 }); | |||
| 23933 | discountValue->setColor(makeColor(201, 162, 100, 255)); | |||
| 23934 | ||||
| 23935 | auto currentGoldText = bgFrame->addField("current gold", 32); | |||
| 23936 | currentGoldText->setFont(valueFont); | |||
| 23937 | currentGoldText->setText(""); | |||
| 23938 | currentGoldText->setHJustify(Field::justify_t::RIGHT); | |||
| 23939 | currentGoldText->setVJustify(Field::justify_t::TOP); | |||
| 23940 | currentGoldText->setSize(SDL_Rect{ bgFrame->getSize().w - 80 - 18, bgFrame->getSize().h - 92, 80, 24 }); | |||
| 23941 | currentGoldText->setColor(makeColor(201, 162, 100, 255)); | |||
| 23942 | ||||
| 23943 | auto currentGoldLabelText = bgFrame->addField("current gold label", 32); | |||
| 23944 | currentGoldLabelText->setFont(valueFont); | |||
| 23945 | currentGoldLabelText->setText(Language::get(4119)); | |||
| 23946 | currentGoldLabelText->setHJustify(Field::justify_t::RIGHT); | |||
| 23947 | currentGoldLabelText->setVJustify(Field::justify_t::TOP); | |||
| 23948 | currentGoldLabelText->setSize(SDL_Rect{ bgFrame->getSize().w - 106 - 100 - 12, bgFrame->getSize().h - 92, 100, 24 }); | |||
| 23949 | currentGoldLabelText->setTextColor(makeColor(201, 162, 100, 255)); | |||
| 23950 | currentGoldLabelText->setOutlineColor(makeColor(29, 16, 11, 255)); | |||
| 23951 | ||||
| 23952 | auto changeGoldText = bgFrame->addField("change gold", 32); | |||
| 23953 | changeGoldText->setFont(valueFont); | |||
| 23954 | changeGoldText->setText(""); | |||
| 23955 | changeGoldText->setHJustify(Field::justify_t::RIGHT); | |||
| 23956 | changeGoldText->setVJustify(Field::justify_t::TOP); | |||
| 23957 | changeGoldText->setSize(SDL_Rect{ bgFrame->getSize().w - 80 - 18, bgFrame->getSize().h - 92, 80, 24 }); | |||
| 23958 | changeGoldText->setColor(makeColor(233, 220, 70, 255)); | |||
| 23959 | changeGoldText->setOntop(true); | |||
| 23960 | } | |||
| 23961 | ||||
| 23962 | { | |||
| 23963 | auto promptFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 23964 | auto buybackText = bgFrame->addField("buyback txt", 32); | |||
| 23965 | buybackText->setFont(promptFont); | |||
| 23966 | buybackText->setText(Language::get(4120)); | |||
| 23967 | buybackText->setHJustify(Field::justify_t::LEFT); | |||
| 23968 | buybackText->setVJustify(Field::justify_t::TOP); | |||
| 23969 | buybackText->setSize(SDL_Rect{ bgFrame->getSize().w - 178, bgFrame->getSize().h - 58, 178, 24 }); | |||
| 23970 | buybackText->setTextColor(makeColor(201, 162, 100, 255)); | |||
| 23971 | //buybackText->setOutlineColor(makeColor(29, 16, 11, 255)); | |||
| 23972 | buybackText->setOutlineColor(makeColor(0, 0, 0, 255)); | |||
| 23973 | ||||
| 23974 | auto buybackGlyph = bgFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, | |||
| 23975 | "", "buyback glyph"); | |||
| 23976 | buybackGlyph->disabled = true; | |||
| 23977 | ||||
| 23978 | auto buybackBtn = bgFrame->addButton("buyback button"); | |||
| 23979 | buybackBtn->setSize(SDL_Rect{ bgFrame->getSize().w - 208, bgFrame->getSize().h - 50, 194, 26 }); | |||
| 23980 | buybackBtn->setFont(promptFont); | |||
| 23981 | buybackBtn->setText(Language::get(4120)); | |||
| 23982 | buybackBtn->setColor(makeColor(255, 255, 255, 255)); | |||
| 23983 | buybackBtn->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 23984 | buybackBtn->setHideGlyphs(true); | |||
| 23985 | buybackBtn->setHideKeyboardGlyphs(true); | |||
| 23986 | buybackBtn->setHideSelectors(true); | |||
| 23987 | buybackBtn->setMenuConfirmControlType(0); | |||
| 23988 | buybackBtn->setBackground("*#images/ui/Shop/Shop_Buyback_Button_00.png"); | |||
| 23989 | buybackBtn->setBackgroundHighlighted("*#images/ui/Shop/Shop_Buyback_ButtonHigh_00.png"); | |||
| 23990 | buybackBtn->setBackgroundActivated("*#images/ui/Shop/Shop_Buyback_ButtonPress_00.png"); | |||
| 23991 | buybackBtn->setTextHighlightColor(makeColor(201, 162, 100, 255)); | |||
| 23992 | buybackBtn->setCallback([](Button& button) { | |||
| 23993 | toggleShopBuybackView(button.getOwner()); | |||
| 23994 | Player::soundActivate(); | |||
| 23995 | }); | |||
| 23996 | ||||
| 23997 | auto closeText = bgFrame->addField("close shop prompt", 32); | |||
| 23998 | closeText->setFont(promptFont); | |||
| 23999 | closeText->setText(Language::get(4121)); | |||
| 24000 | closeText->setHJustify(Field::justify_t::LEFT); | |||
| 24001 | closeText->setVJustify(Field::justify_t::TOP); | |||
| 24002 | closeText->setSize(SDL_Rect{ bgFrame->getSize().w - 178, bgFrame->getSize().h - 36, 178, 24 }); | |||
| 24003 | closeText->setTextColor(makeColor(201, 162, 100, 255)); | |||
| 24004 | //closeText->setOutlineColor(makeColor(29, 16, 11, 255)); | |||
| 24005 | closeText->setOutlineColor(makeColor(0, 0, 0, 255)); | |||
| 24006 | ||||
| 24007 | auto closeGlyph = bgFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, | |||
| 24008 | "", "close shop glyph"); | |||
| 24009 | closeGlyph->disabled = true; | |||
| 24010 | //closeText->setColor(makeColor(233, 220, 70, 255)); | |||
| 24011 | } | |||
| 24012 | } | |||
| 24013 | ||||
| 24014 | const int inventorySlotSize = players[player]->inventoryUI.getSlotSize(); | |||
| 24015 | ||||
| 24016 | shopGUI.shopSlotFrames.clear(); | |||
| 24017 | ||||
| 24018 | const int baseSlotOffsetX = 0; | |||
| 24019 | const int baseSlotOffsetY = 0; | |||
| 24020 | ||||
| 24021 | SDL_Rect invSlotsPos{ 12, 16, 208, 216 }; | |||
| 24022 | { | |||
| 24023 | const auto shopSlotsFrame = frame->addFrame("shop slots"); | |||
| 24024 | shopSlotsFrame->setSize(invSlotsPos); | |||
| 24025 | shopSlotsFrame->setHollow(true); | |||
| 24026 | ||||
| 24027 | /*auto gridImg = chestSlotsFrame->addImage(SDL_Rect{ baseSlotOffsetX, baseSlotOffsetY, 162, gridHeight * numGrids }, | |||
| 24028 | makeColor(255, 255, 255, 32), "*#images/ui/Inventory/HUD_Chest4x3_ScrollGrid.png", "grid img"); | |||
| 24029 | gridImg->tiled = true;*/ | |||
| 24030 | ||||
| 24031 | SDL_Rect currentSlotPos{ baseSlotOffsetX, baseSlotOffsetY, inventorySlotSize, inventorySlotSize }; | |||
| 24032 | const int maxShopX = Player::ShopGUI_t::MAX_SHOP_X; | |||
| 24033 | const int maxShopY = Player::ShopGUI_t::MAX_SHOP_Y; | |||
| 24034 | ||||
| 24035 | int accumulateSlotOffsetX = 0; | |||
| 24036 | for ( int x = 0; x < maxShopX; ++x ) | |||
| 24037 | { | |||
| 24038 | currentSlotPos.x = baseSlotOffsetX + (x * inventorySlotSize) + accumulateSlotOffsetX; | |||
| 24039 | for ( int y = 0; y < maxShopY; ++y ) | |||
| 24040 | { | |||
| 24041 | currentSlotPos.y = baseSlotOffsetY + (y * (inventorySlotSize + 4)); | |||
| 24042 | ||||
| 24043 | char slotname[32] = ""; | |||
| 24044 | snprintf(slotname, sizeof(slotname), "shop %d %d", x, y); | |||
| 24045 | ||||
| 24046 | auto slotFrame = shopSlotsFrame->addFrame(slotname); | |||
| 24047 | shopGUI.shopSlotFrames[x + y * 100] = slotFrame; | |||
| 24048 | SDL_Rect slotPos{ currentSlotPos.x, currentSlotPos.y, inventorySlotSize, inventorySlotSize }; | |||
| 24049 | slotFrame->setSize(slotPos); | |||
| 24050 | ||||
| 24051 | createPlayerInventorySlotFrameElements(slotFrame); | |||
| 24052 | } | |||
| 24053 | ||||
| 24054 | if ( x == 0 || x == 3 ) | |||
| 24055 | { | |||
| 24056 | accumulateSlotOffsetX += 4; | |||
| 24057 | } | |||
| 24058 | } | |||
| 24059 | } | |||
| 24060 | ||||
| 24061 | { | |||
| 24062 | auto buyTooltipFrame = frame->addFrame("buy tooltip frame"); | |||
| 24063 | buyTooltipFrame->setHollow(true); | |||
| 24064 | buyTooltipFrame->setBorder(0); | |||
| 24065 | buyTooltipFrame->setSize(SDL_Rect{ 4, basePos.h - 66, 310, 66 }); | |||
| 24066 | buyTooltipFrame->setDisabled(true); | |||
| 24067 | ||||
| 24068 | auto itemTooltipImg = buyTooltipFrame->addImage(SDL_Rect{ 0, 0, 310, 66 }, 0xFFFFFFFF, | |||
| 24069 | "*#images/ui/Shop/Shop_Tooltip_2Row_00.png", "tooltip img"); | |||
| 24070 | ||||
| 24071 | auto itemGoldImg = buyTooltipFrame->addImage(SDL_Rect{ 0, 0, 20, 28 }, 0xFFFFFFFF, | |||
| 24072 | "*#images/ui/Inventory/tooltips/HUD_Tooltip_Icon_Money_00.png", "gold img"); | |||
| 24073 | ||||
| 24074 | auto itemBgImg = buyTooltipFrame->addImage(SDL_Rect{ 0, 0, 54, 54 }, 0xFFFFFFFF, | |||
| 24075 | "*images/ui/Shop/Shop_Buy_BGSurround03.png", "item bg img"); | |||
| 24076 | ||||
| 24077 | auto orbImg = buyTooltipFrame->addImage(SDL_Rect{ 210 - 8, 38, 16, 16 }, 0xFFFFFFFF, | |||
| 24078 | "", "orb img"); | |||
| 24079 | orbImg->disabled = true; | |||
| 24080 | ||||
| 24081 | auto slotFrame = buyTooltipFrame->addFrame("item slot frame"); | |||
| 24082 | SDL_Rect slotPos{ 0, 0, players[player]->inventoryUI.getSlotSize(), players[player]->inventoryUI.getSlotSize() }; | |||
| 24083 | slotFrame->setSize(slotPos); | |||
| 24084 | slotFrame->setDisabled(true); | |||
| 24085 | createPlayerInventorySlotFrameElements(slotFrame); | |||
| 24086 | ||||
| 24087 | auto itemFont = "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 24088 | auto itemNameText = buyTooltipFrame->addField("item display name", 1024); | |||
| 24089 | itemNameText->setFont(itemFont); | |||
| 24090 | itemNameText->setText(""); | |||
| 24091 | itemNameText->setHJustify(Field::justify_t::LEFT); | |||
| 24092 | itemNameText->setVJustify(Field::justify_t::TOP); | |||
| 24093 | itemNameText->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 24094 | itemNameText->setColor(hudColors.characterSheetLightNeutral); | |||
| 24095 | auto itemValueText = buyTooltipFrame->addField("item display value", 1024); | |||
| 24096 | itemValueText->setFont(itemFont); | |||
| 24097 | itemValueText->setText(""); | |||
| 24098 | itemValueText->setHJustify(Field::justify_t::LEFT); | |||
| 24099 | itemValueText->setVJustify(Field::justify_t::TOP); | |||
| 24100 | itemValueText->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 24101 | itemValueText->setColor(makeColor(201, 162, 100, 255)); | |||
| 24102 | ||||
| 24103 | auto buyPromptText = buyTooltipFrame->addField("buy prompt txt", 128); | |||
| 24104 | buyPromptText->setFont(itemFont); | |||
| 24105 | buyPromptText->setText(""); | |||
| 24106 | buyPromptText->setHJustify(Field::justify_t::LEFT); | |||
| 24107 | buyPromptText->setVJustify(Field::justify_t::TOP); | |||
| 24108 | buyPromptText->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 24109 | buyPromptText->setColor(makeColor(255, 255, 255, 255)); | |||
| 24110 | auto buyPromptFrame = buyTooltipFrame->addFrame("buy prompt frame"); | |||
| 24111 | buyPromptFrame->setHollow(true); | |||
| 24112 | buyPromptFrame->setBorder(0); | |||
| 24113 | buyPromptFrame->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 24114 | buyPromptFrame->setDisabled(true); | |||
| 24115 | auto buyPromptGlyph = buyPromptFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, | |||
| 24116 | "", "buy prompt glyph"); | |||
| 24117 | } | |||
| 24118 | ||||
| 24119 | if ( auto buttomEdgeCoverFrame = frame->addFrame("shop bottom edge frame") ) | |||
| 24120 | { | |||
| 24121 | buttomEdgeCoverFrame->setSize(SDL_Rect{ 0, basePos.h - 10, basePos.w, 10 }); | |||
| 24122 | buttomEdgeCoverFrame->setHollow(true); | |||
| 24123 | buttomEdgeCoverFrame->setBorder(0); | |||
| 24124 | auto bottomEdgeCover = buttomEdgeCoverFrame->addImage(SDL_Rect{ 0, 0, basePos.w, 10 }, | |||
| 24125 | makeColor(255, 255, 255, 255), | |||
| 24126 | "*#images/ui/Shop/Shop_BottomEdgeCover_00.png", "shop bottom edge img"); | |||
| 24127 | } | |||
| 24128 | } | |||
| 24129 | ||||
| 24130 | void createPlayerInventory(const int player) | |||
| 24131 | { | |||
| 24132 | char name[32]; | |||
| 24133 | snprintf(name, sizeof(name), "player inventory %d", player); | |||
| 24134 | Frame* frame = gameUIFrame[player]->addFrame(name); | |||
| 24135 | players[player]->inventoryUI.frame = frame; | |||
| 24136 | frame->setSize(SDL_Rect{ players[player]->camera_virtualx1(), | |||
| 24137 | players[player]->camera_virtualy1(), | |||
| 24138 | players[player]->camera_virtualWidth(), | |||
| 24139 | players[player]->camera_virtualHeight() }); | |||
| 24140 | frame->setHollow(true); | |||
| 24141 | frame->setBorder(0); | |||
| 24142 | frame->setOwner(player); | |||
| 24143 | frame->setInheritParentFrameOpacity(false); | |||
| 24144 | ||||
| 24145 | createChestGUI(player); | |||
| 24146 | createShopGUI(player); | |||
| 24147 | ||||
| 24148 | SDL_Rect basePos{ 0, 0, 210, 448 }; | |||
| 24149 | { | |||
| 24150 | auto bgFrame = frame->addFrame("inventory base"); | |||
| 24151 | playerInventoryFrames[player].inventoryBaseImagesFrame = bgFrame; | |||
| 24152 | bgFrame->setSize(basePos); | |||
| 24153 | bgFrame->setHollow(true); | |||
| 24154 | const auto bgSize = bgFrame->getSize(); | |||
| 24155 | auto defaultInvImg = bgFrame->addImage(SDL_Rect{ 0, 0, bgSize.w, 448 }, | |||
| 24156 | makeColor( 255, 255, 255, 255), | |||
| 24157 | "*#images/ui/Inventory/HUD_Inventory_Base_02.png", "inventory base img"); | |||
| 24158 | defaultInvImg->disabled = true; | |||
| 24159 | playerInventoryFrames[player].defaultInvImg = defaultInvImg; | |||
| 24160 | ||||
| 24161 | auto compactBase = bgFrame->addImage(SDL_Rect{ 0, 0, 210, 250 }, | |||
| 24162 | makeColor( 255, 255, 255, 255), | |||
| 24163 | "*#images/ui/Inventory/HUD_Inventory_BaseCompact_02.png", "inventory base compact img"); | |||
| 24164 | compactBase->disabled = true; | |||
| 24165 | playerInventoryFrames[player].compactInvImg = compactBase; | |||
| 24166 | ||||
| 24167 | auto compactCharacterView = bgFrame->addImage(SDL_Rect{ 0, 0, 210, 214 }, | |||
| 24168 | makeColor( 255, 255, 255, 255), | |||
| 24169 | "*#images/ui/Inventory/HUD_Inventory_CharacterCompact_02.png", "inventory character compact img"); | |||
| 24170 | compactCharacterView->disabled = true; | |||
| 24171 | playerInventoryFrames[player].compactCharImg = compactCharacterView; | |||
| 24172 | } | |||
| 24173 | ||||
| 24174 | { | |||
| 24175 | auto backpackFrame = frame->addFrame("inventory backpack"); | |||
| 24176 | playerInventoryFrames[player].backpackFrame = backpackFrame; | |||
| 24177 | backpackFrame->setSize(SDL_Rect{ 0, 202 + 242 - 2, 226, 102 }); | |||
| 24178 | auto backpackImg = backpackFrame->addImage(SDL_Rect{ 0, 0, 226, 102 }, | |||
| 24179 | makeColor( 255, 255, 255, 255), | |||
| 24180 | "*#images/ui/Inventory/HUD_Inventory_Base_Bag_00a.png", "inventory backpack img"); | |||
| 24181 | } | |||
| 24182 | ||||
| 24183 | const int inventorySlotSize = players[player]->inventoryUI.getSlotSize(); | |||
| 24184 | ||||
| 24185 | players[player]->inventoryUI.slotFrames.clear(); | |||
| 24186 | ||||
| 24187 | const int baseSlotOffsetX = 4; | |||
| 24188 | const int baseSlotOffsetY = 0; | |||
| 24189 | SDL_Rect invSlotsPos{ 0, 202, basePos.w, 242 }; | |||
| 24190 | { | |||
| 24191 | const auto invSlotsFrame = frame->addFrame("inventory slots"); | |||
| 24192 | playerInventoryFrames[player].invSlotsFrame = invSlotsFrame; | |||
| 24193 | invSlotsFrame->setSize(invSlotsPos); | |||
| 24194 | ||||
| 24195 | SDL_Rect currentSlotPos{ baseSlotOffsetX, baseSlotOffsetY, inventorySlotSize, inventorySlotSize }; | |||
| 24196 | ||||
| 24197 | for ( int x = 0; x < players[player]->inventoryUI.getSizeX(); ++x ) | |||
| 24198 | { | |||
| 24199 | currentSlotPos.x = baseSlotOffsetX + (x * inventorySlotSize); | |||
| 24200 | for ( int y = 0; y < players[player]->inventoryUI.DEFAULT_INVENTORY_SIZEY; ++y ) | |||
| 24201 | { | |||
| 24202 | currentSlotPos.y = baseSlotOffsetY + (y * inventorySlotSize); | |||
| 24203 | ||||
| 24204 | char slotname[32] = ""; | |||
| 24205 | snprintf(slotname, sizeof(slotname), "slot %d %d", x, y); | |||
| 24206 | ||||
| 24207 | auto slotFrame = invSlotsFrame->addFrame(slotname); | |||
| 24208 | players[player]->inventoryUI.slotFrames[x + y * 100] = slotFrame; | |||
| 24209 | SDL_Rect slotPos{ currentSlotPos.x, currentSlotPos.y, inventorySlotSize, inventorySlotSize }; | |||
| 24210 | slotFrame->setSize(slotPos); | |||
| 24211 | //slotFrame->setDisabled(true); | |||
| 24212 | ||||
| 24213 | createPlayerInventorySlotFrameElements(slotFrame); | |||
| 24214 | } | |||
| 24215 | } | |||
| 24216 | //invSlotsFrame->setBlitChildren(true); | |||
| 24217 | } | |||
| 24218 | ||||
| 24219 | SDL_Rect backpackSlotsPos{ 0, 202 + 242, basePos.w, 242 }; | |||
| 24220 | { | |||
| 24221 | const auto backPackSlotsFrame = frame->addFrame("backpack slots"); | |||
| 24222 | playerInventoryFrames[player].backpackSlotsFrame = backPackSlotsFrame; | |||
| 24223 | backPackSlotsFrame->setSize(backpackSlotsPos); | |||
| 24224 | const int backpackBaseSlotOffsetY = 8; | |||
| 24225 | int lowestY = 0; | |||
| 24226 | ||||
| 24227 | SDL_Rect currentSlotPos{ baseSlotOffsetX, backpackBaseSlotOffsetY, inventorySlotSize, inventorySlotSize }; | |||
| 24228 | ||||
| 24229 | for ( int x = 0; x < players[player]->inventoryUI.getSizeX(); ++x ) | |||
| 24230 | { | |||
| 24231 | currentSlotPos.x = baseSlotOffsetX + (x * inventorySlotSize); | |||
| 24232 | if ( x == 0 ) { currentSlotPos.x -= 4; } // backpack has unique first/last column entries | |||
| 24233 | if ( x == players[player]->inventoryUI.getSizeX() - 1 ) { currentSlotPos.x += 4; } | |||
| 24234 | ||||
| 24235 | for ( int y = players[player]->inventoryUI.DEFAULT_INVENTORY_SIZEY; | |||
| 24236 | y < players[player]->inventoryUI.DEFAULT_INVENTORY_SIZEY + players[player]->inventoryUI.getPlayerBackpackBonusSizeY(); ++y ) | |||
| 24237 | { | |||
| 24238 | currentSlotPos.y = backpackBaseSlotOffsetY + ((y - players[player]->inventoryUI.DEFAULT_INVENTORY_SIZEY) * inventorySlotSize); | |||
| 24239 | ||||
| 24240 | char slotname[32] = ""; | |||
| 24241 | snprintf(slotname, sizeof(slotname), "slot %d %d", x, y); | |||
| 24242 | ||||
| 24243 | auto slotFrame = backPackSlotsFrame->addFrame(slotname); | |||
| 24244 | players[player]->inventoryUI.slotFrames[x + y * 100] = slotFrame; | |||
| 24245 | SDL_Rect slotPos{ currentSlotPos.x, currentSlotPos.y, inventorySlotSize, inventorySlotSize }; | |||
| 24246 | slotFrame->setSize(slotPos); | |||
| 24247 | lowestY = std::max(slotPos.y + slotPos.h, lowestY); | |||
| 24248 | //slotFrame->setDisabled(true); | |||
| 24249 | ||||
| 24250 | createPlayerInventorySlotFrameElements(slotFrame); | |||
| 24251 | } | |||
| 24252 | } | |||
| 24253 | backpackSlotsPos.h = lowestY; | |||
| 24254 | backPackSlotsFrame->setSize(backpackSlotsPos); | |||
| 24255 | } | |||
| 24256 | ||||
| 24257 | { | |||
| 24258 | SDL_Rect dollSlotsPos{ 0, 0, basePos.w, invSlotsPos.y }; | |||
| 24259 | const auto dollSlotsFrame = frame->addFrame("paperdoll slots"); | |||
| 24260 | playerInventoryFrames[player].dollSlotsFrame = dollSlotsFrame; | |||
| 24261 | dollSlotsFrame->setSize(dollSlotsPos); | |||
| 24262 | ||||
| 24263 | SDL_Rect currentSlotPos{ baseSlotOffsetX, baseSlotOffsetY, inventorySlotSize, inventorySlotSize }; | |||
| 24264 | ||||
| 24265 | for ( int x = Player::Inventory_t::PaperDollColumns::DOLL_COLUMN_LEFT; x <= Player::Inventory_t::PaperDollColumns::DOLL_COLUMN_RIGHT; ++x ) | |||
| 24266 | { | |||
| 24267 | currentSlotPos.x = baseSlotOffsetX; | |||
| 24268 | if ( x == Player::Inventory_t::PaperDollColumns::DOLL_COLUMN_RIGHT ) | |||
| 24269 | { | |||
| 24270 | currentSlotPos.x = baseSlotOffsetX + (4 * inventorySlotSize); // 4 slots over | |||
| 24271 | } | |||
| 24272 | ||||
| 24273 | for ( int y = Player::Inventory_t::PaperDollRows::DOLL_ROW_1; y <= Player::Inventory_t::PaperDollRows::DOLL_ROW_5; ++y ) | |||
| 24274 | { | |||
| 24275 | currentSlotPos.y = baseSlotOffsetY + ((y - Player::Inventory_t::PaperDollRows::DOLL_ROW_1) * inventorySlotSize); | |||
| 24276 | ||||
| 24277 | char slotname[32] = ""; | |||
| 24278 | snprintf(slotname, sizeof(slotname), "slot %d %d", x, y); | |||
| 24279 | ||||
| 24280 | auto slotFrame = dollSlotsFrame->addFrame(slotname); | |||
| 24281 | players[player]->inventoryUI.slotFrames[x + y * 100] = slotFrame; | |||
| 24282 | SDL_Rect slotPos{ currentSlotPos.x, currentSlotPos.y, inventorySlotSize, inventorySlotSize }; | |||
| 24283 | slotFrame->setSize(slotPos); | |||
| 24284 | //slotFrame->setDisabled(true); | |||
| 24285 | ||||
| 24286 | createPlayerInventorySlotFrameElements(slotFrame); | |||
| 24287 | } | |||
| 24288 | } | |||
| 24289 | ||||
| 24290 | { | |||
| 24291 | auto charFrame = frame->addFrame("inventory character preview"); | |||
| 24292 | playerInventoryFrames[player].characterPreview = charFrame; | |||
| 24293 | auto charSize = dollSlotsPos; | |||
| 24294 | charSize.x += inventorySlotSize + baseSlotOffsetX + 4; | |||
| 24295 | charSize.w -= 2 * (inventorySlotSize + baseSlotOffsetX + 4); | |||
| 24296 | charFrame->setSize(charSize); | |||
| 24297 | charFrame->setTickCallback([](Widget& widget) { | |||
| 24298 | Frame* frame = static_cast<Frame*>(&widget); | |||
| 24299 | int player = widget.getOwner(); | |||
| 24300 | auto& scrollInertia = players[player]->paperDoll.portraitRotationInertia; | |||
| 24301 | auto& scrollPercent = players[player]->paperDoll.portraitRotationPercent; | |||
| 24302 | auto& portraitYaw = players[player]->paperDoll.portraitYaw; | |||
| 24303 | static ConsoleVariable<float> cvar_char_portrait_spd("/char_portrait_spd", 15.0); | |||
| 24304 | static ConsoleVariable<float> cvar_char_portrait_decel("/char_portrait_decel", 25.0); | |||
| 24305 | ||||
| 24306 | bool close = false; | |||
| 24307 | if ( players[player]->GUI.activeModule == Player::GUI_t::MODULE_PORTRAIT ) | |||
| 24308 | { | |||
| 24309 | SDL_Rect size = frame->getAbsoluteSize(); | |||
| 24310 | ||||
| 24311 | // make sure to adjust absolute size to camera viewport | |||
| 24312 | const int offsetX = 4; | |||
| 24313 | const int offsetY = 6; | |||
| 24314 | size.x += offsetX; | |||
| 24315 | size.y += offsetY; | |||
| 24316 | size.w -= offsetX * 2; | |||
| 24317 | size.h -= offsetY * 2; | |||
| 24318 | size.x -= players[player]->camera_virtualx1(); | |||
| 24319 | size.y -= players[player]->camera_virtualy1(); | |||
| 24320 | ||||
| 24321 | players[player]->hud.updateCursorAnimation(size.x - 1, size.y - 1, | |||
| 24322 | size.w, size.h, inputs.getVirtualMouse(player)->draw_cursor); | |||
| 24323 | players[player]->paperDoll.portraitActiveToEdit = true; | |||
| 24324 | ||||
| 24325 | if ( inputs.bPlayerUsingKeyboardControl(player) ) | |||
| 24326 | { | |||
| 24327 | if ( Input::inputs[player].binaryToggle("InventoryCharacterRotateLeftMouse") ) | |||
| 24328 | { | |||
| 24329 | scrollInertia = std::min(scrollInertia + .05 / *cvar_char_portrait_spd, .05); | |||
| 24330 | } | |||
| 24331 | if ( Input::inputs[player].binaryToggle("InventoryCharacterRotateRightMouse") ) | |||
| 24332 | { | |||
| 24333 | scrollInertia = std::max(scrollInertia - .05 / *cvar_char_portrait_spd, -.05); | |||
| 24334 | } | |||
| 24335 | close |= Input::inputs[player].consumeBinaryToggle("MenuLeftClick"); | |||
| 24336 | close |= Input::inputs[player].consumeBinaryToggle("MenuRightClick"); | |||
| 24337 | } | |||
| 24338 | if ( inputs.hasController(player) ) | |||
| 24339 | { | |||
| 24340 | close |= Input::inputs[player].consumeBinaryToggle("MenuConfirm"); | |||
| 24341 | close |= Input::inputs[player].consumeBinaryToggle("MenuCancel"); | |||
| 24342 | } | |||
| 24343 | if ( close ) | |||
| 24344 | { | |||
| 24345 | Player::soundCancel(); | |||
| 24346 | } | |||
| 24347 | ||||
| 24348 | if ( players[player]->shootmode ) | |||
| 24349 | { | |||
| 24350 | close = true; | |||
| 24351 | } | |||
| 24352 | ||||
| 24353 | if ( Input::inputs[player].analog("InventoryCharacterRotateRight") ) | |||
| 24354 | { | |||
| 24355 | scrollInertia = 0.0; | |||
| 24356 | real_t delta = Input::inputs[player].analog("InventoryCharacterRotateRight"); | |||
| 24357 | scrollPercent = (scrollPercent + .05 * (getFPSScale(60.0)) * delta); | |||
| 24358 | while ( scrollPercent >= 1.0 ) | |||
| 24359 | { | |||
| 24360 | scrollPercent -= 1.0; | |||
| 24361 | } | |||
| 24362 | } | |||
| 24363 | else if ( Input::inputs[player].analog("InventoryCharacterRotateLeft") ) | |||
| 24364 | { | |||
| 24365 | scrollInertia = 0.0; | |||
| 24366 | real_t delta = Input::inputs[player].analog("InventoryCharacterRotateLeft"); | |||
| 24367 | scrollPercent = scrollPercent - .05 * (getFPSScale(60.0)) * delta; | |||
| 24368 | while ( scrollPercent < 0.0 ) | |||
| 24369 | { | |||
| 24370 | scrollPercent += 1.0; | |||
| 24371 | } | |||
| 24372 | } | |||
| 24373 | ||||
| 24374 | if ( abs(scrollInertia) > 0.0 ) | |||
| 24375 | { | |||
| 24376 | scrollInertia *= .9; | |||
| 24377 | if ( abs(scrollInertia) < (.01 / *cvar_char_portrait_decel) ) | |||
| 24378 | { | |||
| 24379 | scrollInertia = 0.0; | |||
| 24380 | } | |||
| 24381 | scrollPercent += scrollInertia; | |||
| 24382 | } | |||
| 24383 | ||||
| 24384 | if ( Input::inputs[player].consumeBinaryToggle("ResetPortraitRotation") ) | |||
| 24385 | { | |||
| 24386 | Input::inputs[player].consumeBindingsSharedWithBinding("ResetPortraitRotation"); | |||
| 24387 | scrollPercent = 0.0; | |||
| 24388 | scrollInertia = 0.0; | |||
| 24389 | portraitYaw = (330) * PI3.14159265358979323846 / 180; | |||
| 24390 | close = true; | |||
| 24391 | Player::soundCancel(); | |||
| 24392 | } | |||
| 24393 | } | |||
| 24394 | ||||
| 24395 | if ( close ) | |||
| 24396 | { | |||
| 24397 | if ( !inputs.getVirtualMouse(player)->draw_cursor ) | |||
| 24398 | { | |||
| 24399 | players[player]->GUI.returnToPreviousActiveModule(); | |||
| 24400 | } | |||
| 24401 | else | |||
| 24402 | { | |||
| 24403 | players[player]->GUI.activateModule(Player::GUI_t::MODULE_NONE); | |||
| 24404 | } | |||
| 24405 | } | |||
| 24406 | if ( players[player]->GUI.activeModule != Player::GUI_t::MODULE_PORTRAIT ) | |||
| 24407 | { | |||
| 24408 | players[player]->paperDoll.portraitActiveToEdit = false; | |||
| 24409 | } | |||
| 24410 | portraitYaw = (330) * PI3.14159265358979323846 / 180 + (scrollPercent * 2 * PI3.14159265358979323846); | |||
| 24411 | if ( portraitYaw > 2 * PI3.14159265358979323846 ) | |||
| 24412 | { | |||
| 24413 | portraitYaw -= 2 * PI3.14159265358979323846; | |||
| 24414 | } | |||
| 24415 | if ( portraitYaw < 0.0 ) | |||
| 24416 | { | |||
| 24417 | portraitYaw += 2 * PI3.14159265358979323846; | |||
| 24418 | } | |||
| 24419 | }); | |||
| 24420 | charFrame->setDrawCallback([](const Widget& widget, SDL_Rect pos) { | |||
| 24421 | drawCharacterPreview(widget.getOwner(), pos, 50, players[widget.getOwner()]->paperDoll.portraitYaw); | |||
| 24422 | }); | |||
| 24423 | ||||
| 24424 | /*charFrame->addImage(SDL_Rect{ 0, 0, charSize.w, charSize.h }, | |||
| 24425 | makeColor( 255, 255, 255, 255), | |||
| 24426 | "images/system/white.png", "inventory character preview bg");*/ | |||
| 24427 | } | |||
| 24428 | } | |||
| 24429 | ||||
| 24430 | createPlayerSpellList(player); | |||
| 24431 | ||||
| 24432 | { | |||
| 24433 | auto selectedFrame = frame->addFrame("inventory selected item"); | |||
| 24434 | playerInventoryFrames[player].selectedSlotFrame = selectedFrame; | |||
| 24435 | selectedFrame->setSize(SDL_Rect{ 0, 0, inventorySlotSize, inventorySlotSize }); | |||
| 24436 | selectedFrame->setDisabled(true); | |||
| 24437 | ||||
| 24438 | Uint32 color = makeColor( 255, 255, 0, 255); | |||
| 24439 | selectedFrame->addImage(SDL_Rect{ 0, 0, selectedFrame->getSize().w, selectedFrame->getSize().h }, | |||
| 24440 | color, "*images/system/hotbar_slot.png", "inventory selected highlight"); | |||
| 24441 | ||||
| 24442 | auto oldSelectedFrame = frame->addFrame("inventory old selected item"); | |||
| 24443 | oldSelectedFrame->setSize(SDL_Rect{ 0, 0, inventorySlotSize, inventorySlotSize }); | |||
| 24444 | oldSelectedFrame->setDisabled(true); | |||
| 24445 | playerInventoryFrames[player].oldSelectedSlotFrame = oldSelectedFrame; | |||
| 24446 | ||||
| 24447 | const int itemSpriteSize = players[player]->inventoryUI.getItemSpriteSize(); | |||
| 24448 | SDL_Rect itemSpriteBorder{ 2, 2, itemSpriteSize, itemSpriteSize }; | |||
| 24449 | ||||
| 24450 | color = makeColor( 0, 255, 255, 255); | |||
| 24451 | auto oldImg = oldSelectedFrame->addImage(itemSpriteBorder, | |||
| 24452 | makeColor( 255, 255, 255, 128), "", "inventory old selected item"); | |||
| 24453 | playerInventoryFrames[player].oldSelectedSlotItemImg = oldImg; | |||
| 24454 | oldImg->disabled = true; | |||
| 24455 | oldSelectedFrame->addImage(SDL_Rect{ 0, 0, oldSelectedFrame->getSize().w, oldSelectedFrame->getSize().h }, | |||
| 24456 | color, "*images/system/hotbar_slot.png", "inventory old selected highlight"); | |||
| 24457 | ||||
| 24458 | auto bgFrame = frame->findFrame("inventory base"); | |||
| 24459 | playerInventoryFrames[player].inventoryBgFrame = bgFrame; | |||
| 24460 | auto flourishFrame = frame->addFrame("inventory base flourish"); | |||
| 24461 | playerInventoryFrames[player].flourishFrame = flourishFrame; | |||
| 24462 | const int flourishW = 126; | |||
| 24463 | const int flourishH = 26; | |||
| 24464 | flourishFrame->setHollow(true); | |||
| 24465 | flourishFrame->setSize(SDL_Rect{ (bgFrame->getSize().w / 2) - (flourishW / 2), 202 - flourishH + 6, flourishW, flourishH }); | |||
| 24466 | auto flourishImg = flourishFrame->addImage(SDL_Rect{ 0, 0, flourishFrame->getSize().w, flourishFrame->getSize().h }, | |||
| 24467 | makeColor( 255, 255, 255, 255), | |||
| 24468 | "*#images/ui/Inventory/HUD_Inventory_Flourish_00.png", "inventory flourish img"); | |||
| 24469 | //flourishImg->disabled = true; | |||
| 24470 | ||||
| 24471 | { | |||
| 24472 | SDL_Rect charSize = playerInventoryFrames[player].characterPreview->getSize(); | |||
| 24473 | auto autosortFrame = frame->addFrame("autosort frame"); | |||
| 24474 | playerInventoryFrames[player].autosortFrame = autosortFrame; | |||
| 24475 | autosortFrame->setHollow(true); | |||
| 24476 | autosortFrame->setSize(charSize); | |||
| 24477 | auto autosortButton = autosortFrame->addButton("autosort button"); | |||
| 24478 | autosortButton->setSize(SDL_Rect{ charSize.w - 26, | |||
| 24479 | charSize.h - 26 - 16, 26, 26 }); | |||
| 24480 | autosortButton->setBackground("*#images/ui/Inventory/HUD_Button_AutosortUnselect.png"); | |||
| 24481 | autosortButton->setBackgroundActivated("*#images/ui/Inventory/HUD_Button_AutosortPress.png"); | |||
| 24482 | autosortButton->setBackgroundHighlighted("*#images/ui/Inventory/HUD_Button_AutosortSelect.png"); | |||
| 24483 | autosortButton->setHideGlyphs(true); | |||
| 24484 | autosortButton->setHideKeyboardGlyphs(true); | |||
| 24485 | autosortButton->setHideSelectors(true); | |||
| 24486 | autosortButton->setMenuConfirmControlType(0); | |||
| 24487 | //autosortButton->setOntop(true); | |||
| 24488 | autosortButton->setColor(makeColor(255, 255, 255, 255)); | |||
| 24489 | autosortButton->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 24490 | autosortButton->setCallback([](Button& button) { | |||
| 24491 | autosortInventory(button.getOwner()); | |||
| 24492 | //playSound(139, 64); | |||
| 24493 | Player::soundActivate(); | |||
| 24494 | }); | |||
| 24495 | autosortButton->setTickCallback([](Widget& widget) { | |||
| 24496 | if ( widget.isSelected() | |||
| 24497 | && (players[widget.getOwner()]->GUI.activeModule != Player::GUI_t::MODULE_INVENTORY | |||
| 24498 | || players[widget.getOwner()]->shootmode | |||
| 24499 | || !inputs.getVirtualMouse(widget.getOwner())->draw_cursor) ) | |||
| 24500 | { | |||
| 24501 | widget.deselect(); | |||
| 24502 | } | |||
| 24503 | }); | |||
| 24504 | auto autosortImg = autosortFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "autosort glyph"); | |||
| 24505 | autosortImg->disabled = true; | |||
| 24506 | autosortImg->ontop = true; | |||
| 24507 | } | |||
| 24508 | ||||
| 24509 | GenericGUI[player].tinkerGUI.tinkerFrame = frame->addFrame("tinker"); | |||
| 24510 | GenericGUI[player].tinkerGUI.tinkerFrame->setHollow(true); | |||
| 24511 | GenericGUI[player].tinkerGUI.tinkerFrame->setBorder(0); | |||
| 24512 | GenericGUI[player].tinkerGUI.tinkerFrame->setOwner(player); | |||
| 24513 | GenericGUI[player].tinkerGUI.tinkerFrame->setInheritParentFrameOpacity(false); | |||
| 24514 | GenericGUI[player].tinkerGUI.tinkerFrame->setDisabled(true); | |||
| 24515 | ||||
| 24516 | GenericGUI[player].alchemyGUI.alchFrame = frame->addFrame("alchemy"); | |||
| 24517 | GenericGUI[player].alchemyGUI.alchFrame->setHollow(true); | |||
| 24518 | GenericGUI[player].alchemyGUI.alchFrame->setBorder(0); | |||
| 24519 | GenericGUI[player].alchemyGUI.alchFrame->setOwner(player); | |||
| 24520 | GenericGUI[player].alchemyGUI.alchFrame->setInheritParentFrameOpacity(false); | |||
| 24521 | GenericGUI[player].alchemyGUI.alchFrame->setDisabled(true); | |||
| 24522 | ||||
| 24523 | GenericGUI[player].featherGUI.featherFrame = frame->addFrame("feather"); | |||
| 24524 | GenericGUI[player].featherGUI.featherFrame->setHollow(true); | |||
| 24525 | GenericGUI[player].featherGUI.featherFrame->setBorder(0); | |||
| 24526 | GenericGUI[player].featherGUI.featherFrame->setOwner(player); | |||
| 24527 | GenericGUI[player].featherGUI.featherFrame->setInheritParentFrameOpacity(false); | |||
| 24528 | GenericGUI[player].featherGUI.featherFrame->setDisabled(true); | |||
| 24529 | ||||
| 24530 | GenericGUI[player].itemfxGUI.itemEffectFrame = frame->addFrame("itemfx"); | |||
| 24531 | GenericGUI[player].itemfxGUI.itemEffectFrame->setHollow(true); | |||
| 24532 | GenericGUI[player].itemfxGUI.itemEffectFrame->setBorder(0); | |||
| 24533 | GenericGUI[player].itemfxGUI.itemEffectFrame->setOwner(player); | |||
| 24534 | GenericGUI[player].itemfxGUI.itemEffectFrame->setInheritParentFrameOpacity(false); | |||
| 24535 | GenericGUI[player].itemfxGUI.itemEffectFrame->setDisabled(true); | |||
| 24536 | ||||
| 24537 | auto oldCursorFrame = frame->addFrame("inventory old item cursor"); | |||
| 24538 | oldCursorFrame->setSize(SDL_Rect{ 0, 0, inventorySlotSize + 16, inventorySlotSize + 16 }); | |||
| 24539 | oldCursorFrame->setDisabled(true); | |||
| 24540 | oldCursorFrame->setHollow(true); | |||
| 24541 | color = makeColor( 255, 255, 255, oldSelectedCursorOpacity); | |||
| 24542 | oldCursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 24543 | color, "*#images/ui/Inventory/SelectorGrey_TL.png", "inventory old cursor topleft"); | |||
| 24544 | oldCursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 24545 | color, "*#images/ui/Inventory/SelectorGrey_TR.png", "inventory old cursor topright"); | |||
| 24546 | oldCursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 24547 | color, "*#images/ui/Inventory/SelectorGrey_BL.png", "inventory old cursor bottomleft"); | |||
| 24548 | oldCursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 24549 | color, "*#images/ui/Inventory/SelectorGrey_BR.png", "inventory old cursor bottomright"); | |||
| 24550 | ||||
| 24551 | auto cursorFrame = frame->addFrame("inventory selected item cursor"); | |||
| 24552 | players[player]->inventoryUI.selectedItemCursorFrame = cursorFrame; | |||
| 24553 | cursorFrame->setSize(SDL_Rect{ 0, 0, inventorySlotSize + 16, inventorySlotSize + 16 }); | |||
| 24554 | cursorFrame->setDisabled(true); | |||
| 24555 | cursorFrame->setHollow(true); | |||
| 24556 | color = makeColor( 255, 255, 255, selectedCursorOpacity); | |||
| 24557 | cursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 24558 | color, "*#images/ui/Inventory/Selector_TL.png", "inventory selected cursor topleft"); | |||
| 24559 | cursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 24560 | color, "*#images/ui/Inventory/Selector_TR.png", "inventory selected cursor topright"); | |||
| 24561 | cursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 24562 | color, "*#images/ui/Inventory/Selector_BL.png", "inventory selected cursor bottomleft"); | |||
| 24563 | cursorFrame->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 24564 | color, "*#images/ui/Inventory/Selector_BR.png", "inventory selected cursor bottomright"); | |||
| 24565 | } | |||
| 24566 | ||||
| 24567 | { | |||
| 24568 | auto draggingInventoryItem = frame->addFrame("dragging inventory item"); | |||
| 24569 | draggingInventoryItem->setSize(SDL_Rect{ 0, 0, inventorySlotSize, inventorySlotSize }); | |||
| 24570 | draggingInventoryItem->setDisabled(true); | |||
| 24571 | createPlayerInventorySlotFrameElements(draggingInventoryItem); | |||
| 24572 | } | |||
| 24573 | ||||
| 24574 | { | |||
| 24575 | // unused for now, only animating cycling items | |||
| 24576 | auto draggingInventoryItemOld = frame->addFrame("dragging inventory item old"); | |||
| 24577 | const int itemSpriteSize = players[player]->inventoryUI.getItemSpriteSize(); | |||
| 24578 | SDL_Rect draggingInventoryItemPos{ 2, 2, inventorySlotSize - 2, inventorySlotSize - 2 }; | |||
| 24579 | const int alignOffset = (draggingInventoryItemPos.w - itemSpriteSize) / 2; // align the item sprite within the box by this offset to center | |||
| 24580 | draggingInventoryItemPos.x += alignOffset; | |||
| 24581 | draggingInventoryItemPos.y += alignOffset; | |||
| 24582 | draggingInventoryItemPos.w = itemSpriteSize; | |||
| 24583 | draggingInventoryItemPos.h = itemSpriteSize; | |||
| 24584 | draggingInventoryItemOld->setSize(draggingInventoryItemPos); | |||
| 24585 | draggingInventoryItemOld->setDisabled(true); | |||
| 24586 | ||||
| 24587 | SDL_Rect imgPos{ 0, 0, draggingInventoryItemOld->getSize().w, draggingInventoryItemOld->getSize().h }; | |||
| 24588 | auto itemSprite = draggingInventoryItemOld->addImage(imgPos, 0xFFFFFFFF, "", "item sprite img"); | |||
| 24589 | } | |||
| 24590 | } | |||
| 24591 | ||||
| 24592 | void Player::Inventory_t::updateSelectedSlotAnimation(int destx, int desty, int width, int height, bool usingMouse) | |||
| 24593 | { | |||
| 24594 | if ( frame ) | |||
| 24595 | { | |||
| 24596 | if ( selectedItemCursorFrame ) | |||
| 24597 | { | |||
| 24598 | if ( usingMouse ) | |||
| 24599 | { | |||
| 24600 | selectedItemCursorFrame->setSize( | |||
| 24601 | SDL_Rect{ | |||
| 24602 | destx - cursor.cursorToSlotOffset, | |||
| 24603 | desty - cursor.cursorToSlotOffset, | |||
| 24604 | width + 2 * (cursor.cursorToSlotOffset + 1), | |||
| 24605 | height + 2 * (cursor.cursorToSlotOffset + 1) | |||
| 24606 | } | |||
| 24607 | ); | |||
| 24608 | cursor.animateSetpointX = destx; | |||
| 24609 | cursor.animateSetpointY = desty; | |||
| 24610 | cursor.animateStartX = destx; | |||
| 24611 | cursor.animateStartY = desty; | |||
| 24612 | } | |||
| 24613 | else if ( cursor.animateSetpointX != destx || cursor.animateSetpointY != desty ) | |||
| 24614 | { | |||
| 24615 | SDL_Rect size = selectedItemCursorFrame->getSize(); | |||
| 24616 | cursor.animateStartX = size.x; | |||
| 24617 | cursor.animateStartY = size.y; | |||
| 24618 | size.w = width + 2 * (cursor.cursorToSlotOffset + 1); | |||
| 24619 | size.h = height + 2 * (cursor.cursorToSlotOffset + 1); | |||
| 24620 | selectedItemCursorFrame->setSize(size); | |||
| 24621 | cursor.animateSetpointX = destx; | |||
| 24622 | cursor.animateSetpointY = desty; | |||
| 24623 | cursor.animateX = 0.0; | |||
| 24624 | cursor.animateY = 0.0; | |||
| 24625 | cursor.lastUpdateTick = ticks; | |||
| 24626 | } | |||
| 24627 | } | |||
| 24628 | } | |||
| 24629 | //messagePlayer(player.playernum, "%d %d", destx, desty); | |||
| 24630 | } | |||
| 24631 | ||||
| 24632 | void Player::Inventory_t::updateItemContextMenu() | |||
| 24633 | { | |||
| 24634 | Uint32& itemMenuItem = inputs.getUIInteraction(player.playernum)->itemMenuItem; | |||
| 24635 | bool& itemMenuOpen = inputs.getUIInteraction(player.playernum)->itemMenuOpen; | |||
| 24636 | int& itemMenuSelected = inputs.getUIInteraction(player.playernum)->itemMenuSelected; | |||
| 24637 | bool& itemMenuFromHotbar = inputs.getUIInteraction(player.playernum)->itemMenuFromHotbar; | |||
| 24638 | ||||
| 24639 | Item* item = uidToItem(itemMenuItem); | |||
| 24640 | if ( itemMenuItem != 0 && !item ) | |||
| 24641 | { | |||
| 24642 | if ( chestGUI.bOpen && openedChest[player.playernum] ) | |||
| 24643 | { | |||
| 24644 | list_t* chest_inventory = nullptr; | |||
| 24645 | if ( multiplayer == CLIENT2 ) | |||
| 24646 | { | |||
| 24647 | chest_inventory = &chestInv[player.playernum]; | |||
| 24648 | } | |||
| 24649 | else if ( openedChest[player.playernum]->children.first && openedChest[player.playernum]->children.first->element ) | |||
| 24650 | { | |||
| 24651 | chest_inventory = (list_t*)openedChest[player.playernum]->children.first->element; | |||
| 24652 | } | |||
| 24653 | if ( chest_inventory ) | |||
| 24654 | { | |||
| 24655 | node_t* nextnode = nullptr; | |||
| 24656 | for ( node_t* node = chest_inventory->first; node != NULL__null; node = nextnode ) | |||
| 24657 | { | |||
| 24658 | nextnode = node->next; | |||
| 24659 | Item* chestItem = (Item*)node->element; | |||
| 24660 | if ( !chestItem ) { continue; } | |||
| 24661 | if ( chestItem->uid == itemMenuItem ) | |||
| 24662 | { | |||
| 24663 | item = chestItem; | |||
| 24664 | break; | |||
| 24665 | } | |||
| 24666 | } | |||
| 24667 | } | |||
| 24668 | } | |||
| 24669 | } | |||
| 24670 | ||||
| 24671 | if ( !interactFrame ) | |||
| 24672 | { | |||
| 24673 | itemMenuOpen = false; | |||
| 24674 | return; | |||
| 24675 | } | |||
| 24676 | ||||
| 24677 | ||||
| 24678 | if ( !item || !itemMenuOpen ) | |||
| 24679 | { | |||
| 24680 | itemMenuOpen = false; | |||
| 24681 | itemMenuSelected = 0; | |||
| 24682 | itemMenuFromHotbar = false; | |||
| 24683 | interactFrame->setDisabled(true); | |||
| 24684 | return; | |||
| 24685 | } | |||
| 24686 | ||||
| 24687 | bool& toggleclick = inputs.getUIInteraction(player.playernum)->toggleclick; | |||
| 24688 | int& itemMenuX = inputs.getUIInteraction(player.playernum)->itemMenuX; | |||
| 24689 | int& itemMenuY = inputs.getUIInteraction(player.playernum)->itemMenuY; | |||
| 24690 | int& itemMenuOffsetDetectionY = inputs.getUIInteraction(player.playernum)->itemMenuOffsetDetectionY; | |||
| 24691 | itemMenuOffsetDetectionY = 0; | |||
| 24692 | const Sint32 mousex = (inputs.getMouse(player.playernum, Inputs::X) / (float)xres) * (float)Frame::virtualScreenX; | |||
| 24693 | const Sint32 mousey = (inputs.getMouse(player.playernum, Inputs::Y) / (float)yres) * (float)Frame::virtualScreenY; | |||
| 24694 | ||||
| 24695 | auto highlightImageMid = interactFrame->findImage("interact selected highlight mid"); | |||
| 24696 | highlightImageMid->disabled = true; | |||
| 24697 | highlightImageMid->color = hudColors.itemContextMenuOptionSelectedImg; | |||
| 24698 | auto highlightImageLeft = interactFrame->findImage("interact selected highlight left"); | |||
| 24699 | highlightImageLeft->disabled = true; | |||
| 24700 | highlightImageLeft->color = hudColors.itemContextMenuOptionSelectedImg; | |||
| 24701 | auto highlightImageRight = interactFrame->findImage("interact selected highlight right"); | |||
| 24702 | highlightImageRight->disabled = true; | |||
| 24703 | highlightImageRight->color = hudColors.itemContextMenuOptionSelectedImg; | |||
| 24704 | ||||
| 24705 | interactFrame->setDisabled(false); | |||
| 24706 | ||||
| 24707 | auto options = getContextMenuOptionsForItem(player.playernum, item); | |||
| 24708 | if ( itemMenuFromHotbar ) | |||
| 24709 | { | |||
| 24710 | options.push_back(PROMPT_CLEAR_HOTBAR_SLOT); | |||
| 24711 | std::reverse(options.begin(), options.end()); | |||
| 24712 | if ( itemCategory(item) == SPELLBOOK ) | |||
| 24713 | { | |||
| 24714 | for ( auto& it : options ) | |||
| 24715 | { | |||
| 24716 | if ( it == PROMPT_INTERACT ) | |||
| 24717 | { | |||
| 24718 | it = PROMPT_INTERACT_SPELLBOOK_HOTBAR; | |||
| 24719 | } | |||
| 24720 | } | |||
| 24721 | } | |||
| 24722 | } | |||
| 24723 | std::vector<std::pair<Frame::image_t*, Field*>> optionFrames; | |||
| 24724 | auto glyph1 = interactFrame->findImage("glyph 1"); | |||
| 24725 | auto option1 = interactFrame->findField("interact option 1"); | |||
| 24726 | auto glyph2 = interactFrame->findImage("glyph 2"); | |||
| 24727 | auto option2 = interactFrame->findField("interact option 2"); | |||
| 24728 | auto glyph3 = interactFrame->findImage("glyph 3"); | |||
| 24729 | auto option3 = interactFrame->findField("interact option 3"); | |||
| 24730 | auto glyph4 = interactFrame->findImage("glyph 4"); | |||
| 24731 | auto option4 = interactFrame->findField("interact option 4"); | |||
| 24732 | auto glyph5 = interactFrame->findImage("glyph 5"); | |||
| 24733 | auto option5 = interactFrame->findField("interact option 5"); | |||
| 24734 | if ( glyph1 && option1 ) | |||
| 24735 | { | |||
| 24736 | optionFrames.push_back(std::make_pair(glyph1, option1)); | |||
| 24737 | } | |||
| 24738 | if ( glyph2 && option2 ) | |||
| 24739 | { | |||
| 24740 | optionFrames.push_back(std::make_pair(glyph2, option2)); | |||
| 24741 | } | |||
| 24742 | if ( glyph3 && option3 ) | |||
| 24743 | { | |||
| 24744 | optionFrames.push_back(std::make_pair(glyph3, option3)); | |||
| 24745 | } | |||
| 24746 | if ( glyph4 && option4 ) | |||
| 24747 | { | |||
| 24748 | optionFrames.push_back(std::make_pair(glyph4, option4)); | |||
| 24749 | } | |||
| 24750 | if ( glyph5 && option5 ) | |||
| 24751 | { | |||
| 24752 | optionFrames.push_back(std::make_pair(glyph5, option5)); | |||
| 24753 | } | |||
| 24754 | ||||
| 24755 | size_t index = 0; | |||
| 24756 | unsigned int maxWidth = 0; | |||
| 24757 | if ( auto interactText = interactFrame->findField("interact text") ) | |||
| 24758 | { | |||
| 24759 | interactText->setColor(hudColors.itemContextMenuHeadingText); | |||
| 24760 | if ( auto textGet = Text::get(interactText->getText(), interactText->getFont(), | |||
| 24761 | makeColor(255, 255, 255, 255), makeColor(0, 0, 0, 255)) ) | |||
| 24762 | { | |||
| 24763 | maxWidth = textGet->getWidth(); | |||
| 24764 | } | |||
| 24765 | } | |||
| 24766 | int maxHeight = 0; | |||
| 24767 | const int textPaddingX = 8; | |||
| 24768 | ||||
| 24769 | for ( auto& optionPair : optionFrames ) | |||
| 24770 | { | |||
| 24771 | auto& img = optionPair.first; | |||
| 24772 | auto& txt = optionPair.second; | |||
| 24773 | txt->setColor(hudColors.itemContextMenuOptionText); | |||
| 24774 | if ( index >= options.size() ) | |||
| 24775 | { | |||
| 24776 | txt->setDisabled(true); | |||
| 24777 | img->disabled = true; | |||
| 24778 | continue; | |||
| 24779 | } | |||
| 24780 | ||||
| 24781 | txt->setDisabled(false); | |||
| 24782 | img->disabled = true; | |||
| 24783 | auto promptType = options[index]; | |||
| 24784 | ||||
| 24785 | // in-case we want controller support here. | |||
| 24786 | /*switch ( promptType ) | |||
| 24787 | { | |||
| 24788 | case PROMPT_EQUIP: | |||
| 24789 | case PROMPT_UNEQUIP: | |||
| 24790 | case PROMPT_SPELL_EQUIP: | |||
| 24791 | img->path = Input::inputs[player.playernum].getGlyphPathForBinding("MenuAlt1"); | |||
| 24792 | break; | |||
| 24793 | case PROMPT_APPRAISE: | |||
| 24794 | img->path = Input::inputs[player.playernum].getGlyphPathForBinding("MenuAlt2"); | |||
| 24795 | break; | |||
| 24796 | case PROMPT_DROP: | |||
| 24797 | img->path = Input::inputs[player.playernum].getGlyphPathForBinding("MenuCancel"); | |||
| 24798 | break; | |||
| 24799 | default: | |||
| 24800 | img->path = Input::inputs[player.playernum].getGlyphPathForBinding("MenuConfirm"); | |||
| 24801 | break; | |||
| 24802 | } | |||
| 24803 | ||||
| 24804 | if ( img->path == "" ) | |||
| 24805 | { | |||
| 24806 | img->disabled = true; | |||
| 24807 | }*/ | |||
| 24808 | ||||
| 24809 | txt->setText(getContextMenuLangEntry(player.playernum, promptType, *item)); | |||
| 24810 | if ( auto textGet = Text::get(txt->getText(), txt->getFont(), | |||
| 24811 | makeColor(255, 255, 255, 255), makeColor(0, 0, 0, 255)) ) | |||
| 24812 | { | |||
| 24813 | maxWidth = std::max(textGet->getWidth(), maxWidth); | |||
| 24814 | ||||
| 24815 | SDL_Rect size = txt->getSize(); | |||
| 24816 | size.w = textGet->getWidth(); | |||
| 24817 | if ( img->disabled ) | |||
| 24818 | { | |||
| 24819 | size.x = textPaddingX; | |||
| 24820 | txt->setHJustify(Field::justify_t::CENTER); | |||
| 24821 | } | |||
| 24822 | else | |||
| 24823 | { | |||
| 24824 | size.x = img->pos.x + img->pos.w + textPaddingX; | |||
| 24825 | txt->setHJustify(Field::justify_t::LEFT); | |||
| 24826 | } | |||
| 24827 | txt->setSize(size); | |||
| 24828 | } | |||
| 24829 | ||||
| 24830 | maxHeight = std::max(img->pos.y + img->pos.h, maxHeight); | |||
| 24831 | ++index; | |||
| 24832 | } | |||
| 24833 | ||||
| 24834 | //maxWidth += 16; -- edit this to add extra left/right padding | |||
| 24835 | ||||
| 24836 | const int rightClickProtectBuffer = (right_click_protect ? 0 : 10); | |||
| 24837 | ||||
| 24838 | bool alignRight = true; | |||
| 24839 | if ( itemMenuFromHotbar ) | |||
| 24840 | { | |||
| 24841 | alignRight = true; | |||
| 24842 | } | |||
| 24843 | else if ( bCompactView ) | |||
| 24844 | { | |||
| 24845 | if ( player.paperDoll.isItemOnDoll(*item) ) | |||
| 24846 | { | |||
| 24847 | if ( paperDollPanelJustify == PanelJustify_t::PANEL_JUSTIFY_RIGHT ) | |||
| 24848 | { | |||
| 24849 | alignRight = false; | |||
| 24850 | } | |||
| 24851 | else | |||
| 24852 | { | |||
| 24853 | alignRight = true; | |||
| 24854 | } | |||
| 24855 | } | |||
| 24856 | else if ( itemCategory(item) == SPELL_CAT ) | |||
| 24857 | { | |||
| 24858 | if ( spellPanel.panelJustify == PanelJustify_t::PANEL_JUSTIFY_RIGHT ) | |||
| 24859 | { | |||
| 24860 | alignRight = false; | |||
| 24861 | } | |||
| 24862 | else | |||
| 24863 | { | |||
| 24864 | alignRight = true; | |||
| 24865 | } | |||
| 24866 | } | |||
| 24867 | else if ( isItemFromChest(item) ) | |||
| 24868 | { | |||
| 24869 | if ( inventoryPanelJustify == PanelJustify_t::PANEL_JUSTIFY_RIGHT ) | |||
| 24870 | { | |||
| 24871 | alignRight = true; | |||
| 24872 | } | |||
| 24873 | else | |||
| 24874 | { | |||
| 24875 | alignRight = false; | |||
| 24876 | } | |||
| 24877 | } | |||
| 24878 | else | |||
| 24879 | { | |||
| 24880 | // normal inventory items | |||
| 24881 | if ( inventoryPanelJustify == PanelJustify_t::PANEL_JUSTIFY_RIGHT ) | |||
| 24882 | { | |||
| 24883 | alignRight = false; | |||
| 24884 | } | |||
| 24885 | else | |||
| 24886 | { | |||
| 24887 | alignRight = true; | |||
| 24888 | } | |||
| 24889 | } | |||
| 24890 | } | |||
| 24891 | ||||
| 24892 | const int textStartX = (glyph1->disabled ? 0 : glyph1->pos.x + glyph1->pos.w) + textPaddingX; | |||
| 24893 | const int frameWidth = maxWidth + textStartX + textPaddingX; | |||
| 24894 | ||||
| 24895 | SDL_Rect frameSize = interactFrame->getSize(); | |||
| 24896 | frameSize.x = itemMenuX; | |||
| 24897 | frameSize.y = itemMenuY; | |||
| 24898 | ||||
| 24899 | // position the frame elements | |||
| 24900 | int interimHeight = 0; | |||
| 24901 | { | |||
| 24902 | auto tl = interactFrame->findImage("interact top left"); | |||
| 24903 | auto tmid = interactFrame->findImage("interact top background"); | |||
| 24904 | tmid->pos.w = frameWidth - tl->pos.w * 2; | |||
| 24905 | auto tr = interactFrame->findImage("interact top right"); | |||
| 24906 | tr->pos.x = tmid->pos.x + tmid->pos.w; | |||
| 24907 | ||||
| 24908 | interimHeight = tmid->pos.y + tmid->pos.h; | |||
| 24909 | frameSize.w = tr->pos.x + tr->pos.w; | |||
| 24910 | } | |||
| 24911 | { | |||
| 24912 | const int middleOffsetY = 13; | |||
| 24913 | auto ml = interactFrame->findImage("interact middle left"); | |||
| 24914 | ml->pos.h = maxHeight - interimHeight - middleOffsetY; | |||
| 24915 | auto mmid = interactFrame->findImage("interact middle background"); | |||
| 24916 | mmid->pos.h = ml->pos.h; | |||
| 24917 | mmid->pos.w = frameWidth - (ml->pos.w) * 2; | |||
| 24918 | mmid->color = hudColors.itemContextMenuOptionImg; | |||
| 24919 | auto mr = interactFrame->findImage("interact middle right"); | |||
| 24920 | mr->pos.h = ml->pos.h; | |||
| 24921 | mr->pos.x = mmid->pos.x + mmid->pos.w; | |||
| 24922 | ||||
| 24923 | interimHeight = mmid->pos.y + mmid->pos.h; | |||
| 24924 | } | |||
| 24925 | { | |||
| 24926 | auto bl = interactFrame->findImage("interact bottom left"); | |||
| 24927 | bl->pos.y = interimHeight; | |||
| 24928 | auto bmid = interactFrame->findImage("interact bottom background"); | |||
| 24929 | bmid->pos.y = interimHeight; | |||
| 24930 | bmid->pos.w = frameWidth - bl->pos.w * 2; | |||
| 24931 | auto br = interactFrame->findImage("interact bottom right"); | |||
| 24932 | br->pos.y = interimHeight; | |||
| 24933 | br->pos.x = bmid->pos.x + bmid->pos.w; | |||
| 24934 | ||||
| 24935 | frameSize.h = br->pos.y + br->pos.h; | |||
| 24936 | } | |||
| 24937 | ||||
| 24938 | if ( auto interactText = interactFrame->findField("interact text") ) | |||
| 24939 | { | |||
| 24940 | SDL_Rect size = interactText->getSize(); | |||
| 24941 | size.x = 0; | |||
| 24942 | size.w = frameSize.w; | |||
| 24943 | interactText->setSize(size); | |||
| 24944 | } | |||
| 24945 | ||||
| 24946 | if ( !alignRight ) | |||
| 24947 | { | |||
| 24948 | frameSize.x -= frameSize.w; | |||
| 24949 | } | |||
| 24950 | ||||
| 24951 | if ( (frameSize.y + frameSize.h) > player.camera_virtualy2() ) | |||
| 24952 | { | |||
| 24953 | int yoffset = (frameSize.y + frameSize.h) - player.camera_virtualy2(); | |||
| 24954 | frameSize.y -= yoffset; | |||
| 24955 | itemMenuOffsetDetectionY = yoffset; | |||
| 24956 | } | |||
| 24957 | interactFrame->setSize(frameSize); | |||
| 24958 | ||||
| 24959 | index = 0; | |||
| 24960 | for ( auto& optionPair : optionFrames ) | |||
| 24961 | { | |||
| 24962 | auto& img = optionPair.first; | |||
| 24963 | auto& txt = optionPair.second; | |||
| 24964 | ||||
| 24965 | if ( txt->getHJustify() == Field::justify_t::CENTER ) | |||
| 24966 | { | |||
| 24967 | SDL_Rect size = txt->getSize(); | |||
| 24968 | size.w = maxWidth; | |||
| 24969 | txt->setSize(size); | |||
| 24970 | } | |||
| 24971 | ||||
| 24972 | if ( index < options.size() ) | |||
| 24973 | { | |||
| 24974 | auto ml = interactFrame->findImage("interact middle left"); | |||
| 24975 | SDL_Rect absoluteSize = txt->getAbsoluteSize(); | |||
| 24976 | absoluteSize.x -= (4 + ml->pos.w) + (alignRight ? rightClickProtectBuffer : 0); | |||
| 24977 | absoluteSize.w += ((4 + ml->pos.w) * 2 + rightClickProtectBuffer); | |||
| 24978 | absoluteSize.y += 4; | |||
| 24979 | absoluteSize.h -= 4; | |||
| 24980 | absoluteSize.y += itemMenuOffsetDetectionY; | |||
| 24981 | if ( mousex >= absoluteSize.x && mousex < absoluteSize.x + absoluteSize.w | |||
| 24982 | && mousey >= absoluteSize.y && mousey < absoluteSize.y + absoluteSize.h ) | |||
| 24983 | { | |||
| 24984 | itemMenuSelected = index; | |||
| 24985 | } | |||
| 24986 | } | |||
| 24987 | ++index; | |||
| 24988 | } | |||
| 24989 | ||||
| 24990 | SDL_Rect absoluteSize = interactFrame->getAbsoluteSize(); | |||
| 24991 | // right click protect uses exact border, else there is 10 px buffer | |||
| 24992 | absoluteSize.x -= (alignRight ? rightClickProtectBuffer : 0); | |||
| 24993 | absoluteSize.w += rightClickProtectBuffer; | |||
| 24994 | absoluteSize.y += itemMenuOffsetDetectionY; | |||
| 24995 | if ( !(mousex >= absoluteSize.x && mousex < absoluteSize.x + absoluteSize.w | |||
| 24996 | && mousey >= absoluteSize.y && mousey < absoluteSize.y + absoluteSize.h) ) | |||
| 24997 | { | |||
| 24998 | itemMenuSelected = -1; | |||
| 24999 | } | |||
| 25000 | ||||
| 25001 | if ( itemMenuSelected >= 0 && itemMenuSelected < options.size() ) | |||
| 25002 | { | |||
| 25003 | auto& txt = optionFrames[itemMenuSelected].second; | |||
| 25004 | txt->setColor(hudColors.itemContextMenuOptionSelectedText); | |||
| 25005 | SDL_Rect size = txt->getSize(); | |||
| 25006 | size.x -= 4; | |||
| 25007 | size.w += 2 * 4; | |||
| 25008 | size.y += 3; | |||
| 25009 | highlightImageMid->pos = size; | |||
| 25010 | highlightImageMid->pos.x += highlightImageLeft->pos.w; | |||
| 25011 | highlightImageMid->pos.w -= 2 * highlightImageLeft->pos.w; | |||
| 25012 | highlightImageMid->pos.h = highlightImageLeft->pos.h; | |||
| 25013 | highlightImageMid->disabled = false; | |||
| 25014 | ||||
| 25015 | highlightImageLeft->pos.x = highlightImageMid->pos.x - highlightImageLeft->pos.w; | |||
| 25016 | highlightImageLeft->pos.y = highlightImageMid->pos.y; | |||
| 25017 | highlightImageLeft->disabled = false; | |||
| 25018 | highlightImageRight->pos.x = highlightImageMid->pos.x + highlightImageMid->pos.w; | |||
| 25019 | highlightImageRight->disabled = false; | |||
| 25020 | highlightImageRight->pos.y = highlightImageMid->pos.y; | |||
| 25021 | } | |||
| 25022 | ||||
| 25023 | bool activateSelection = false; | |||
| 25024 | if ( !Input::inputs[player.playernum].binary("MenuRightClick") && !toggleclick ) | |||
| 25025 | { | |||
| 25026 | activateSelection = true; | |||
| 25027 | } | |||
| 25028 | if ( activateSelection ) | |||
| 25029 | { | |||
| 25030 | if ( itemMenuSelected >= 0 && itemMenuSelected < options.size() ) | |||
| 25031 | { | |||
| 25032 | if ( options[itemMenuSelected] == ItemContextMenuPrompts::PROMPT_DROP | |||
| 25033 | && player.paperDoll.isItemOnDoll(*item) ) | |||
| 25034 | { | |||
| 25035 | // need to unequip | |||
| 25036 | player.inventoryUI.activateItemContextMenuOption(item, ItemContextMenuPrompts::PROMPT_UNEQUIP_FOR_DROP); | |||
| 25037 | player.paperDoll.updateSlots(); | |||
| 25038 | if ( player.paperDoll.isItemOnDoll(*item) ) | |||
| 25039 | { | |||
| 25040 | // couldn't unequip, no more actions | |||
| 25041 | } | |||
| 25042 | else | |||
| 25043 | { | |||
| 25044 | // successfully unequipped, let's drop it. | |||
| 25045 | bool droppedAll = false; | |||
| 25046 | while ( item && item->count > 1 ) | |||
| 25047 | { | |||
| 25048 | droppedAll = dropItem(item, player.playernum); | |||
| 25049 | if ( droppedAll ) | |||
| 25050 | { | |||
| 25051 | item = nullptr; | |||
| 25052 | } | |||
| 25053 | } | |||
| 25054 | if ( !droppedAll ) | |||
| 25055 | { | |||
| 25056 | dropItem(item, player.playernum); | |||
| 25057 | } | |||
| 25058 | } | |||
| 25059 | } | |||
| 25060 | else | |||
| 25061 | { | |||
| 25062 | activateItemContextMenuOption(item, options[itemMenuSelected]); | |||
| 25063 | } | |||
| 25064 | } | |||
| 25065 | //Close the menu. | |||
| 25066 | itemMenuOpen = false; | |||
| 25067 | itemMenuItem = 0; | |||
| 25068 | interactFrame->setDisabled(true); | |||
| 25069 | } | |||
| 25070 | } | |||
| 25071 | ||||
| 25072 | void Player::Inventory_t::activateItemContextMenuOption(Item* item, ItemContextMenuPrompts prompt) | |||
| 25073 | { | |||
| 25074 | if ( !item ) | |||
| 25075 | { | |||
| 25076 | return; | |||
| 25077 | } | |||
| 25078 | const int player = this->player.playernum; | |||
| 25079 | bool disableItemUsage = false; | |||
| 25080 | if ( players[player] && players[player]->entity ) | |||
| 25081 | { | |||
| 25082 | if ( players[player]->entity->effectShapeshift != NOTHING ) | |||
| 25083 | { | |||
| 25084 | // shape shifted, disable some items | |||
| 25085 | if ( !item->usableWhileShapeshifted(stats[player]) ) | |||
| 25086 | { | |||
| 25087 | disableItemUsage = true; | |||
| 25088 | } | |||
| 25089 | if ( item->type == FOOD_CREAMPIE && (prompt == PROMPT_UNEQUIP || prompt == PROMPT_EQUIP) ) | |||
| 25090 | { | |||
| 25091 | disableItemUsage = true; | |||
| 25092 | } | |||
| 25093 | } | |||
| 25094 | else | |||
| 25095 | { | |||
| 25096 | if ( itemCategory(item) == SPELL_CAT && item->appearance >= 1000 ) | |||
| 25097 | { | |||
| 25098 | if ( canUseShapeshiftSpellInCurrentForm(player, *item) != 1 ) | |||
| 25099 | { | |||
| 25100 | disableItemUsage = true; | |||
| 25101 | } | |||
| 25102 | } | |||
| 25103 | } | |||
| 25104 | } | |||
| 25105 | ||||
| 25106 | if ( client_classes[player] == CLASS_SHAMAN ) | |||
| 25107 | { | |||
| 25108 | if ( item->type == SPELL_ITEM && !(playerUnlockedShamanSpell(player, item)) ) | |||
| 25109 | { | |||
| 25110 | disableItemUsage = true; | |||
| 25111 | } | |||
| 25112 | } | |||
| 25113 | ||||
| 25114 | //PROMPT_EQUIP, | |||
| 25115 | //PROMPT_UNEQUIP, | |||
| 25116 | //PROMPT_SPELL_EQUIP, | |||
| 25117 | //PROMPT_INTERACT, | |||
| 25118 | //PROMPT_EAT, | |||
| 25119 | //PROMPT_CONSUME, | |||
| 25120 | //PROMPT_SPELL_QUICKCAST, | |||
| 25121 | //PROMPT_INSPECT, | |||
| 25122 | //PROMPT_SELL, | |||
| 25123 | //PROMPT_BUY, | |||
| 25124 | //PROMPT_STORE_CHEST, | |||
| 25125 | //PROMPT_RETRIEVE_CHEST, | |||
| 25126 | //PROMPT_APPRAISE, | |||
| 25127 | //PROMPT_DROP | |||
| 25128 | ||||
| 25129 | bool sellingItemToShop = false; | |||
| 25130 | if ( players[player]->gui_mode == GUI_MODE_SHOP && itemCategory(item) != SPELL_CAT | |||
| 25131 | && players[player]->shopGUI.bOpen && uidToEntity(shopkeeper[player]) ) | |||
| 25132 | { | |||
| 25133 | sellingItemToShop = true; | |||
| 25134 | } | |||
| 25135 | ||||
| 25136 | if ( prompt == PROMPT_DROPDOWN ) | |||
| 25137 | { | |||
| 25138 | return; | |||
| 25139 | } | |||
| 25140 | if ( prompt == PROMPT_CLEAR_HOTBAR_SLOT ) | |||
| 25141 | { | |||
| 25142 | for ( auto& slot : players[player]->hotbar.slots() ) | |||
| 25143 | { | |||
| 25144 | if ( slot.item == item->uid ) | |||
| 25145 | { | |||
| 25146 | slot.item = 0; | |||
| 25147 | slot.resetLastItem(); | |||
| 25148 | } | |||
| 25149 | } | |||
| 25150 | return; | |||
| 25151 | } | |||
| 25152 | if ( prompt == PROMPT_APPRAISE ) | |||
| 25153 | { | |||
| 25154 | players[player]->inventoryUI.appraisal.appraiseItem(item); | |||
| 25155 | return; | |||
| 25156 | } | |||
| 25157 | else if ( prompt == PROMPT_DROP ) | |||
| 25158 | { | |||
| 25159 | dropItem(item, player); | |||
| 25160 | return; | |||
| 25161 | } | |||
| 25162 | else if ( prompt == PROMPT_SELL ) | |||
| 25163 | { | |||
| 25164 | if ( sellingItemToShop ) | |||
| 25165 | { | |||
| 25166 | sellItemToShop(player, item); | |||
| 25167 | } | |||
| 25168 | return; | |||
| 25169 | } | |||
| 25170 | else if ( prompt == PROMPT_RETRIEVE_CHEST || prompt == PROMPT_RETRIEVE_CHEST_ALL ) | |||
| 25171 | { | |||
| 25172 | bool emptiedSlot = false; | |||
| 25173 | if ( openedChest[player] ) | |||
| 25174 | { | |||
| 25175 | if ( prompt == PROMPT_RETRIEVE_CHEST ) | |||
| 25176 | { | |||
| 25177 | bool tryAddToInventory = true; | |||
| 25178 | while ( tryAddToInventory ) | |||
| 25179 | { | |||
| 25180 | if ( item->count <= 0 ) | |||
| 25181 | { | |||
| 25182 | break; | |||
| 25183 | } | |||
| 25184 | int oldItemQty = 0; | |||
| 25185 | int destItemQty = 0; | |||
| 25186 | int oldQty = item->count; | |||
| 25187 | item->count = 1; | |||
| 25188 | bool oldIdentify = item->identified; | |||
| 25189 | if ( skillCapstoneUnlocked(player, PRO_APPRAISAL) ) | |||
| 25190 | { | |||
| 25191 | item->identified = true; | |||
| 25192 | } | |||
| 25193 | auto result = getItemStackingBehavior(player, item, nullptr, oldItemQty, destItemQty); | |||
| 25194 | item->identified = oldIdentify; | |||
| 25195 | item->count = oldQty; | |||
| 25196 | ||||
| 25197 | int amountToPlace = 1; | |||
| 25198 | switch ( result.resultType ) | |||
| 25199 | { | |||
| 25200 | case ITEM_ADDED_ENTIRELY_TO_DESTINATION_STACK: | |||
| 25201 | case ITEM_ADDED_PARTIALLY_TO_DESTINATION_STACK: | |||
| 25202 | { | |||
| 25203 | // operation success, can finish here. | |||
| 25204 | Item* inventoryItem = takeItemFromChest(player, item, amountToPlace, result.itemToStackInto, false); | |||
| 25205 | tryAddToInventory = false; | |||
| 25206 | if ( oldQty == 1 ) | |||
| 25207 | { | |||
| 25208 | emptiedSlot = true; | |||
| 25209 | } | |||
| 25210 | break; | |||
| 25211 | } | |||
| 25212 | case ITEM_ADDED_WITHOUT_NEEDING_STACK: | |||
| 25213 | { | |||
| 25214 | // check for inventory space | |||
| 25215 | if ( !bItemInventoryHasFreeSlot() ) | |||
| 25216 | { | |||
| 25217 | // no space | |||
| 25218 | tryAddToInventory = false; | |||
| 25219 | messagePlayer(player, MESSAGE_INVENTORY, Language::get(727), item->getName()); // no room | |||
| 25220 | playSoundPlayer(player, 90, 64); | |||
| 25221 | break; | |||
| 25222 | } | |||
| 25223 | ||||
| 25224 | // operation success, can finish here. | |||
| 25225 | int amountToPlace = 1; | |||
| 25226 | Item* inventoryItem = takeItemFromChest(player, item, amountToPlace, nullptr, true); | |||
| 25227 | tryAddToInventory = false; | |||
| 25228 | if ( oldQty == 1 ) | |||
| 25229 | { | |||
| 25230 | emptiedSlot = true; | |||
| 25231 | } | |||
| 25232 | break; | |||
| 25233 | } | |||
| 25234 | default: | |||
| 25235 | // error out | |||
| 25236 | tryAddToInventory = false; | |||
| 25237 | break; | |||
| 25238 | } | |||
| 25239 | } | |||
| 25240 | } | |||
| 25241 | else if ( prompt == PROMPT_RETRIEVE_CHEST_ALL ) | |||
| 25242 | { | |||
| 25243 | bool tryAddToInventory = true; | |||
| 25244 | while ( tryAddToInventory ) | |||
| 25245 | { | |||
| 25246 | if ( item->count <= 0 ) | |||
| 25247 | { | |||
| 25248 | break; | |||
| 25249 | } | |||
| 25250 | int oldItemQty = 0; | |||
| 25251 | int destItemQty = 0; | |||
| 25252 | bool oldIdentify = item->identified; | |||
| 25253 | if ( skillCapstoneUnlocked(player, PRO_APPRAISAL) ) | |||
| 25254 | { | |||
| 25255 | item->identified = true; | |||
| 25256 | } | |||
| 25257 | auto result = getItemStackingBehavior(player, item, nullptr, oldItemQty, destItemQty); | |||
| 25258 | item->identified = oldIdentify; | |||
| 25259 | int amountToPlace = item->count - oldItemQty; | |||
| 25260 | assert(amountToPlace > 0)(static_cast<void> (0)); | |||
| 25261 | if ( amountToPlace <= 0 ) | |||
| 25262 | { | |||
| 25263 | break; | |||
| 25264 | } | |||
| 25265 | switch ( result.resultType ) | |||
| 25266 | { | |||
| 25267 | case ITEM_ADDED_PARTIALLY_TO_DESTINATION_STACK: | |||
| 25268 | { | |||
| 25269 | if ( Item* inventoryItem = takeItemFromChest(player, item, amountToPlace, result.itemToStackInto, false) ) | |||
| 25270 | { | |||
| 25271 | // need to do another place operation. | |||
| 25272 | } | |||
| 25273 | else | |||
| 25274 | { | |||
| 25275 | tryAddToInventory = false; | |||
| 25276 | } | |||
| 25277 | break; | |||
| 25278 | } | |||
| 25279 | case ITEM_ADDED_ENTIRELY_TO_DESTINATION_STACK: | |||
| 25280 | { | |||
| 25281 | Item* inventoryItem = takeItemFromChest(player, item, amountToPlace, result.itemToStackInto, false); | |||
| 25282 | if ( oldItemQty > 0 ) | |||
| 25283 | { | |||
| 25284 | // more work to do (unusually large stacks exceeding normal limits) | |||
| 25285 | } | |||
| 25286 | else | |||
| 25287 | { | |||
| 25288 | // operation success, can finish here. | |||
| 25289 | tryAddToInventory = false; | |||
| 25290 | if ( oldItemQty == 0 ) | |||
| 25291 | { | |||
| 25292 | emptiedSlot = true; | |||
| 25293 | } | |||
| 25294 | } | |||
| 25295 | break; | |||
| 25296 | } | |||
| 25297 | case ITEM_ADDED_WITHOUT_NEEDING_STACK: | |||
| 25298 | { | |||
| 25299 | // check for inventory space | |||
| 25300 | if ( !bItemInventoryHasFreeSlot() ) | |||
| 25301 | { | |||
| 25302 | // no space | |||
| 25303 | tryAddToInventory = false; | |||
| 25304 | messagePlayer(player, MESSAGE_INVENTORY, Language::get(727), item->getName()); // no room | |||
| 25305 | playSoundPlayer(player, 90, 64); | |||
| 25306 | break; | |||
| 25307 | } | |||
| 25308 | Item* inventoryItem = takeItemFromChest(player, item, amountToPlace, nullptr, true); | |||
| 25309 | tryAddToInventory = false; | |||
| 25310 | if ( oldItemQty == 0 ) | |||
| 25311 | { | |||
| 25312 | emptiedSlot = true; | |||
| 25313 | } | |||
| 25314 | break; | |||
| 25315 | } | |||
| 25316 | default: | |||
| 25317 | // error out | |||
| 25318 | tryAddToInventory = false; | |||
| 25319 | break; | |||
| 25320 | } | |||
| 25321 | } | |||
| 25322 | } | |||
| 25323 | } | |||
| 25324 | if ( !emptiedSlot && (inputs.getUIInteraction(player)->itemMenuOpen || players[player]->inventoryUI.bCompactView) ) | |||
| 25325 | { | |||
| 25326 | tooltipDelayTick = ticks + TICKS_PER_SECOND50 / 2; | |||
| 25327 | } | |||
| 25328 | return; | |||
| 25329 | } | |||
| 25330 | else if ( prompt == PROMPT_STORE_CHEST || prompt == PROMPT_STORE_CHEST_ALL ) | |||
| 25331 | { | |||
| 25332 | bool emptiedSlot = false; | |||
| 25333 | if ( !disableItemUsage || (disableItemUsage && !players[player]->paperDoll.isItemOnDoll(*item)) ) | |||
| 25334 | { | |||
| 25335 | if ( openedChest[player] ) | |||
| 25336 | { | |||
| 25337 | if ( prompt == PROMPT_STORE_CHEST ) | |||
| 25338 | { | |||
| 25339 | bool tryAddToChest = true; | |||
| 25340 | while ( tryAddToChest ) | |||
| 25341 | { | |||
| 25342 | if ( item->count <= 0 ) | |||
| 25343 | { | |||
| 25344 | break; | |||
| 25345 | } | |||
| 25346 | int oldItemQty = 0; | |||
| 25347 | int destItemQty = 0; | |||
| 25348 | int oldQty = item->count; | |||
| 25349 | item->count = 1; | |||
| 25350 | auto result = getItemStackingBehaviorIntoChest(player, item, nullptr, oldItemQty, destItemQty); | |||
| 25351 | item->count = oldQty; | |||
| 25352 | ||||
| 25353 | int amountToPlace = 1; | |||
| 25354 | switch ( result.resultType ) | |||
| 25355 | { | |||
| 25356 | case ITEM_ADDED_ENTIRELY_TO_DESTINATION_STACK: | |||
| 25357 | case ITEM_ADDED_PARTIALLY_TO_DESTINATION_STACK: | |||
| 25358 | { | |||
| 25359 | // operation success, can finish here. | |||
| 25360 | Item* itemInChest = openedChest[player]->addItemToChestFromInventory(player, item, amountToPlace, false, result.itemToStackInto); | |||
| 25361 | tryAddToChest = false; | |||
| 25362 | if ( oldQty == 1 ) | |||
| 25363 | { | |||
| 25364 | emptiedSlot = true; | |||
| 25365 | } | |||
| 25366 | break; | |||
| 25367 | } | |||
| 25368 | case ITEM_ADDED_WITHOUT_NEEDING_STACK: | |||
| 25369 | { | |||
| 25370 | // check for chest space | |||
| 25371 | if ( numItemsInChest(player) + 1 > (players[player]->inventoryUI.MAX_CHEST_X * players[player]->inventoryUI.MAX_CHEST_Y) ) | |||
| 25372 | { | |||
| 25373 | // no space | |||
| 25374 | tryAddToChest = false; | |||
| 25375 | messagePlayer(player, MESSAGE_INVENTORY, Language::get(4098), item->getName()); // no room | |||
| 25376 | playSoundPlayer(player, 90, 64); | |||
| 25377 | break; | |||
| 25378 | } | |||
| 25379 | ||||
| 25380 | // operation success, can finish here. | |||
| 25381 | int amountToPlace = 1; | |||
| 25382 | Item* itemInChest = openedChest[player]->addItemToChestFromInventory(player, item, amountToPlace, true, nullptr); | |||
| 25383 | tryAddToChest = false; | |||
| 25384 | if ( oldQty == 1 ) | |||
| 25385 | { | |||
| 25386 | emptiedSlot = true; | |||
| 25387 | } | |||
| 25388 | break; | |||
| 25389 | } | |||
| 25390 | default: | |||
| 25391 | // error out | |||
| 25392 | tryAddToChest = false; | |||
| 25393 | break; | |||
| 25394 | } | |||
| 25395 | } | |||
| 25396 | } | |||
| 25397 | else if ( prompt == PROMPT_STORE_CHEST_ALL ) | |||
| 25398 | { | |||
| 25399 | bool tryAddToChest = true; | |||
| 25400 | while ( tryAddToChest ) | |||
| 25401 | { | |||
| 25402 | if ( item->count <= 0 ) | |||
| 25403 | { | |||
| 25404 | break; | |||
| 25405 | } | |||
| 25406 | int oldItemQty = 0; | |||
| 25407 | int destItemQty = 0; | |||
| 25408 | auto result = getItemStackingBehaviorIntoChest(player, item, nullptr, oldItemQty, destItemQty); | |||
| 25409 | int amountToPlace = item->count - oldItemQty; | |||
| 25410 | assert(amountToPlace > 0)(static_cast<void> (0)); | |||
| 25411 | if ( amountToPlace <= 0 ) | |||
| 25412 | { | |||
| 25413 | break; | |||
| 25414 | } | |||
| 25415 | switch ( result.resultType ) | |||
| 25416 | { | |||
| 25417 | case ITEM_ADDED_PARTIALLY_TO_DESTINATION_STACK: | |||
| 25418 | { | |||
| 25419 | if ( Item* itemInChest = openedChest[player]->addItemToChestFromInventory(player, item, amountToPlace, false, result.itemToStackInto) ) | |||
| 25420 | { | |||
| 25421 | // need to do another place operation. | |||
| 25422 | } | |||
| 25423 | else | |||
| 25424 | { | |||
| 25425 | tryAddToChest = false; | |||
| 25426 | } | |||
| 25427 | break; | |||
| 25428 | } | |||
| 25429 | case ITEM_ADDED_ENTIRELY_TO_DESTINATION_STACK: | |||
| 25430 | { | |||
| 25431 | // operation success, can finish here. | |||
| 25432 | Item* itemInChest = openedChest[player]->addItemToChestFromInventory(player, item, amountToPlace, false, result.itemToStackInto); | |||
| 25433 | tryAddToChest = false; | |||
| 25434 | if ( oldItemQty == 0 ) | |||
| 25435 | { | |||
| 25436 | emptiedSlot = true; | |||
| 25437 | } | |||
| 25438 | break; | |||
| 25439 | } | |||
| 25440 | case ITEM_ADDED_WITHOUT_NEEDING_STACK: | |||
| 25441 | { | |||
| 25442 | // check for chest space | |||
| 25443 | if ( numItemsInChest(player) + 1 > (players[player]->inventoryUI.MAX_CHEST_X * players[player]->inventoryUI.MAX_CHEST_Y) ) | |||
| 25444 | { | |||
| 25445 | // no space | |||
| 25446 | tryAddToChest = false; | |||
| 25447 | messagePlayer(player, MESSAGE_INVENTORY, Language::get(4098), item->getName()); // no room | |||
| 25448 | playSoundPlayer(player, 90, 64); | |||
| 25449 | break; | |||
| 25450 | } | |||
| 25451 | Item* itemInChest = openedChest[player]->addItemToChestFromInventory(player, item, amountToPlace, true, nullptr); | |||
| 25452 | if ( !itemInChest ) | |||
| 25453 | { | |||
| 25454 | tryAddToChest = false; // failure adding to chest | |||
| 25455 | } | |||
| 25456 | else if ( oldItemQty > 0 ) | |||
| 25457 | { | |||
| 25458 | // more work to do (unusually large stacks exceeding normal limits) | |||
| 25459 | } | |||
| 25460 | else | |||
| 25461 | { | |||
| 25462 | tryAddToChest = false; | |||
| 25463 | if ( oldItemQty == 0 ) | |||
| 25464 | { | |||
| 25465 | emptiedSlot = true; | |||
| 25466 | } | |||
| 25467 | } | |||
| 25468 | break; | |||
| 25469 | } | |||
| 25470 | default: | |||
| 25471 | // error out | |||
| 25472 | tryAddToChest = false; | |||
| 25473 | break; | |||
| 25474 | } | |||
| 25475 | } | |||
| 25476 | } | |||
| 25477 | } | |||
| 25478 | } | |||
| 25479 | else | |||
| 25480 | { | |||
| 25481 | messagePlayer(player, MESSAGE_INVENTORY | MESSAGE_HINT | MESSAGE_EQUIPMENT, Language::get(3432)); // unable to use in current form message. | |||
| 25482 | playSoundPlayer(player, 90, 64); | |||
| 25483 | } | |||
| 25484 | if ( !emptiedSlot && (inputs.getUIInteraction(player)->itemMenuOpen || players[player]->inventoryUI.bCompactView) ) | |||
| 25485 | { | |||
| 25486 | tooltipDelayTick = ticks + TICKS_PER_SECOND50 / 2; | |||
| 25487 | } | |||
| 25488 | return; | |||
| 25489 | } | |||
| 25490 | else if ( prompt == PROMPT_GRAB ) | |||
| 25491 | { | |||
| 25492 | inputs.getUIInteraction(player)->selectedItemFromHotbar = -1; | |||
| 25493 | if ( this->player.inventoryUI.isItemFromChest(item) ) | |||
| 25494 | { | |||
| 25495 | inputs.getUIInteraction(player)->selectedItemFromChest = item->uid; | |||
| 25496 | } | |||
| 25497 | inputs.getUIInteraction(player)->selectedItem = item; | |||
| 25498 | playSound(139, 64); // click sound | |||
| 25499 | inputs.getUIInteraction(player)->toggleclick = true; | |||
| 25500 | Input::inputs[player].consumeBinaryToggle("MenuLeftClick"); | |||
| 25501 | return; | |||
| 25502 | } | |||
| 25503 | else if ( prompt == PROMPT_EAT ) | |||
| 25504 | { | |||
| 25505 | if ( !disableItemUsage ) | |||
| 25506 | { | |||
| 25507 | useItem(item, player); | |||
| 25508 | } | |||
| 25509 | return; | |||
| 25510 | } | |||
| 25511 | else if ( prompt == PROMPT_CONSUME || prompt == PROMPT_CONSUME_ALTERNATE ) | |||
| 25512 | { | |||
| 25513 | // consume item | |||
| 25514 | if ( multiplayer == CLIENT2 ) | |||
| 25515 | { | |||
| 25516 | strcpy((char*)net_packet->data, "FODA"); | |||
| 25517 | SDLNet_Write32((Uint32)item->type, &net_packet->data[4])_SDLNet_Write32((Uint32)item->type, &net_packet->data [4]); | |||
| 25518 | SDLNet_Write32((Uint32)item->status, &net_packet->data[8])_SDLNet_Write32((Uint32)item->status, &net_packet-> data[8]); | |||
| 25519 | SDLNet_Write32((Uint32)item->beatitude, &net_packet->data[12])_SDLNet_Write32((Uint32)item->beatitude, &net_packet-> data[12]); | |||
| 25520 | SDLNet_Write32((Uint32)item->count, &net_packet->data[16])_SDLNet_Write32((Uint32)item->count, &net_packet->data [16]); | |||
| 25521 | SDLNet_Write32((Uint32)item->appearance, &net_packet->data[20])_SDLNet_Write32((Uint32)item->appearance, &net_packet-> data[20]); | |||
| 25522 | net_packet->data[24] = item->identified; | |||
| 25523 | net_packet->data[25] = player; | |||
| 25524 | net_packet->address.host = net_server.host; | |||
| 25525 | net_packet->address.port = net_server.port; | |||
| 25526 | net_packet->len = 26; | |||
| 25527 | sendPacketSafe(net_sock, -1, net_packet, 0); | |||
| 25528 | } | |||
| 25529 | item_FoodAutomaton(item, player); | |||
| 25530 | return; | |||
| 25531 | } | |||
| 25532 | else if ( prompt == PROMPT_INTERACT | |||
| 25533 | || prompt == PROMPT_INTERACT_SPELLBOOK_HOTBAR | |||
| 25534 | || prompt == PROMPT_INSPECT | |||
| 25535 | || prompt == PROMPT_INSPECT_ALTERNATE | |||
| 25536 | || prompt == PROMPT_TINKER ) | |||
| 25537 | { | |||
| 25538 | if ( item->type == TOOL_PLAYER_LOOT_BAG ) | |||
| 25539 | { | |||
| 25540 | if ( prompt == PROMPT_INTERACT ) | |||
| 25541 | { | |||
| 25542 | item_ToolLootBag(item, player); | |||
| 25543 | } | |||
| 25544 | else if ( prompt == PROMPT_INSPECT ) | |||
| 25545 | { | |||
| 25546 | useItem(item, player); | |||
| 25547 | } | |||
| 25548 | } | |||
| 25549 | else if ( item->type == TOOL_ALEMBIC ) | |||
| 25550 | { | |||
| 25551 | // not experimenting | |||
| 25552 | if ( GenericGUI[player].alchemyGUI.bOpen && GenericGUI[player].alembicItem == item ) | |||
| 25553 | { | |||
| 25554 | GenericGUI[player].closeGUI(); | |||
| 25555 | } | |||
| 25556 | else if ( !disableItemUsage ) | |||
| 25557 | { | |||
| 25558 | if ( item->status > BROKEN ) | |||
| 25559 | { | |||
| 25560 | GenericGUI[player].openGUI(GUI_TYPE_ALCHEMY, true, item); | |||
| 25561 | } | |||
| 25562 | else | |||
| 25563 | { | |||
| 25564 | messagePlayer(player, MESSAGE_EQUIPMENT, Language::get(1092), item->getName()); // this is useless! | |||
| 25565 | playSoundPlayer(player, 90, 64); | |||
| 25566 | } | |||
| 25567 | } | |||
| 25568 | else | |||
| 25569 | { | |||
| 25570 | messagePlayer(player, MESSAGE_INVENTORY | MESSAGE_HINT | MESSAGE_EQUIPMENT, Language::get(3432)); // unable to use in current form message. | |||
| 25571 | playSoundPlayer(player, 90, 64); | |||
| 25572 | } | |||
| 25573 | } | |||
| 25574 | else if ( item->type == TOOL_TINKERING_KIT ) | |||
| 25575 | { | |||
| 25576 | if ( !disableItemUsage ) | |||
| 25577 | { | |||
| 25578 | if ( true /*item->status > BROKEN*/ ) // allow broken tinker kit | |||
| 25579 | { | |||
| 25580 | GenericGUI[player].openGUI(GUI_TYPE_TINKERING, item); | |||
| 25581 | } | |||
| 25582 | else | |||
| 25583 | { | |||
| 25584 | messagePlayer(player, MESSAGE_EQUIPMENT, Language::get(1092), item->getName()); // this is useless! | |||
| 25585 | playSoundPlayer(player, 90, 64); | |||
| 25586 | } | |||
| 25587 | } | |||
| 25588 | else | |||
| 25589 | { | |||
| 25590 | messagePlayer(player, MESSAGE_INVENTORY | MESSAGE_HINT | MESSAGE_EQUIPMENT, Language::get(3432)); // unable to use in current form message. | |||
| 25591 | playSoundPlayer(player, 90, 64); | |||
| 25592 | } | |||
| 25593 | } | |||
| 25594 | else | |||
| 25595 | { | |||
| 25596 | if ( !disableItemUsage && prompt == PROMPT_INTERACT_SPELLBOOK_HOTBAR ) | |||
| 25597 | { | |||
| 25598 | if ( itemCategory(item) == SPELLBOOK ) | |||
| 25599 | { | |||
| 25600 | players[player]->magic.spellbookUidFromHotbarSlot = item->uid; | |||
| 25601 | } | |||
| 25602 | useItem(item, player); | |||
| 25603 | players[player]->magic.spellbookUidFromHotbarSlot = 0; | |||
| 25604 | } | |||
| 25605 | else if ( !disableItemUsage && prompt == PROMPT_INTERACT ) | |||
| 25606 | { | |||
| 25607 | useItem(item, player); | |||
| 25608 | } | |||
| 25609 | else | |||
| 25610 | { | |||
| 25611 | messagePlayer(player, MESSAGE_INVENTORY | MESSAGE_HINT | MESSAGE_EQUIPMENT, Language::get(3432)); // unable to use in current form message. | |||
| 25612 | playSoundPlayer(player, 90, 64); | |||
| 25613 | } | |||
| 25614 | } | |||
| 25615 | return; | |||
| 25616 | } | |||
| 25617 | else if ( prompt == PROMPT_EQUIP | |||
| 25618 | || prompt == PROMPT_UNEQUIP | |||
| 25619 | || prompt == PROMPT_SPELL_EQUIP | |||
| 25620 | || prompt == PROMPT_UNEQUIP_FOR_DROP ) | |||
| 25621 | { | |||
| 25622 | if ( isItemEquippableInShieldSlot(item) && cast_animation[player].active_spellbook ) | |||
| 25623 | { | |||
| 25624 | return; // don't try to equip shields while casting | |||
| 25625 | } | |||
| 25626 | ||||
| 25627 | if ( !disableItemUsage ) | |||
| 25628 | { | |||
| 25629 | if ( item->status == BROKEN ) | |||
| 25630 | { | |||
| 25631 | messagePlayer(player, MESSAGE_EQUIPMENT, Language::get(1092), item->getName()); // don't try equip broken stuff | |||
| 25632 | playSoundPlayer(player, 90, 64); | |||
| 25633 | return; | |||
| 25634 | } | |||
| 25635 | ||||
| 25636 | if ( prompt == PROMPT_EQUIP | |||
| 25637 | || prompt == PROMPT_UNEQUIP | |||
| 25638 | || prompt == PROMPT_UNEQUIP_FOR_DROP ) | |||
| 25639 | { | |||
| 25640 | if ( items[item->type].item_slot == ItemEquippableSlot::EQUIPPABLE_IN_SLOT_WEAPON | |||
| 25641 | || itemCategory(item) == SPELLBOOK ) | |||
| 25642 | { | |||
| 25643 | if ( prompt == PROMPT_UNEQUIP_FOR_DROP ) | |||
| 25644 | { | |||
| 25645 | playerTryEquipItemAndUpdateServer(player, item, false); // don't check inventory space to unequip | |||
| 25646 | } | |||
| 25647 | else | |||
| 25648 | { | |||
| 25649 | playerTryEquipItemAndUpdateServer(player, item, true); | |||
| 25650 | } | |||
| 25651 | return; | |||
| 25652 | } | |||
| 25653 | } | |||
| 25654 | ||||
| 25655 | if ( prompt == PROMPT_UNEQUIP_FOR_DROP ) | |||
| 25656 | { | |||
| 25657 | useItem(item, player, players[player]->entity, true); | |||
| 25658 | } | |||
| 25659 | else | |||
| 25660 | { | |||
| 25661 | useItem(item, player); | |||
| 25662 | } | |||
| 25663 | return; | |||
| 25664 | } | |||
| 25665 | else | |||
| 25666 | { | |||
| 25667 | if ( client_classes[player] == CLASS_SHAMAN && item->type == SPELL_ITEM ) | |||
| 25668 | { | |||
| 25669 | messagePlayer(player, MESSAGE_INVENTORY | MESSAGE_HINT | MESSAGE_EQUIPMENT, Language::get(3488)); // unable to use with current level. | |||
| 25670 | } | |||
| 25671 | else | |||
| 25672 | { | |||
| 25673 | messagePlayer(player, MESSAGE_INVENTORY | MESSAGE_HINT | MESSAGE_EQUIPMENT, Language::get(3432)); // unable to use in current form message. | |||
| 25674 | } | |||
| 25675 | playSoundPlayer(player, 90, 64); | |||
| 25676 | } | |||
| 25677 | return; | |||
| 25678 | } | |||
| 25679 | else if ( prompt == PROMPT_SPELL_QUICKCAST ) | |||
| 25680 | { | |||
| 25681 | if ( !disableItemUsage ) | |||
| 25682 | { | |||
| 25683 | players[player]->magic.setQuickCastSpellFromInventory(item); | |||
| 25684 | } | |||
| 25685 | else | |||
| 25686 | { | |||
| 25687 | if ( client_classes[player] == CLASS_SHAMAN && item->type == SPELL_ITEM ) | |||
| 25688 | { | |||
| 25689 | messagePlayer(player, MESSAGE_INVENTORY | MESSAGE_HINT | MESSAGE_EQUIPMENT, Language::get(3488)); // unable to use with current level. | |||
| 25690 | } | |||
| 25691 | else | |||
| 25692 | { | |||
| 25693 | messagePlayer(player, MESSAGE_INVENTORY | MESSAGE_HINT | MESSAGE_EQUIPMENT, Language::get(3432)); // unable to use in current form message. | |||
| 25694 | } | |||
| 25695 | playSoundPlayer(player, 90, 64); | |||
| 25696 | } | |||
| 25697 | return; | |||
| 25698 | } | |||
| 25699 | } | |||
| 25700 | ||||
| 25701 | void Player::Hotbar_t::updateSelectedSlotAnimation(int destx, int desty, int width, int height, bool usingMouse) | |||
| 25702 | { | |||
| 25703 | if ( hotbarFrame ) | |||
| 25704 | { | |||
| 25705 | if ( auto selectedSlotCursor = hotbarFrame->findFrame("shootmode selected item cursor") ) | |||
| 25706 | { | |||
| 25707 | if ( usingMouse ) | |||
| 25708 | { | |||
| 25709 | selectedSlotCursor->setSize( | |||
| 25710 | SDL_Rect{ | |||
| 25711 | destx - shootmodeCursor.cursorToSlotOffset, | |||
| 25712 | desty - shootmodeCursor.cursorToSlotOffset, | |||
| 25713 | width + 2 * (shootmodeCursor.cursorToSlotOffset + 1), | |||
| 25714 | height + 2 * (shootmodeCursor.cursorToSlotOffset + 1) | |||
| 25715 | } | |||
| 25716 | ); | |||
| 25717 | shootmodeCursor.animateSetpointX = destx; | |||
| 25718 | shootmodeCursor.animateSetpointY = desty; | |||
| 25719 | shootmodeCursor.animateStartX = destx; | |||
| 25720 | shootmodeCursor.animateStartY = desty; | |||
| 25721 | } | |||
| 25722 | else if ( shootmodeCursor.animateSetpointX != destx || shootmodeCursor.animateSetpointY != desty ) | |||
| 25723 | { | |||
| 25724 | SDL_Rect size = selectedSlotCursor->getSize(); | |||
| 25725 | shootmodeCursor.animateStartX = size.x; | |||
| 25726 | shootmodeCursor.animateStartY = size.y; | |||
| 25727 | size.w = width + 2 * (shootmodeCursor.cursorToSlotOffset + 1); | |||
| 25728 | size.h = height + 2 * (shootmodeCursor.cursorToSlotOffset + 1); | |||
| 25729 | selectedSlotCursor->setSize(size); | |||
| 25730 | shootmodeCursor.animateSetpointX = destx; | |||
| 25731 | shootmodeCursor.animateSetpointY = desty; | |||
| 25732 | shootmodeCursor.animateX = 0.0; | |||
| 25733 | shootmodeCursor.animateY = 0.0; | |||
| 25734 | shootmodeCursor.lastUpdateTick = ticks; | |||
| 25735 | } | |||
| 25736 | } | |||
| 25737 | } | |||
| 25738 | } | |||
| 25739 | ||||
| 25740 | void Player::Inventory_t::updateSelectedItemAnimation() | |||
| 25741 | { | |||
| 25742 | if ( !player.isLocalPlayer() ) | |||
| 25743 | { | |||
| 25744 | return; | |||
| 25745 | } | |||
| 25746 | ||||
| 25747 | if ( frame ) | |||
| 25748 | { | |||
| 25749 | if ( auto selectedSlotFrame = frame->findFrame("inventory selected item") ) | |||
| 25750 | { | |||
| 25751 | selectedSlotFrame->setDisabled(true); | |||
| 25752 | } | |||
| 25753 | if ( selectedItemCursorFrame ) | |||
| 25754 | { | |||
| 25755 | selectedItemCursorFrame->setDisabled(true); | |||
| 25756 | } | |||
| 25757 | } | |||
| 25758 | ||||
| 25759 | if ( inputs.getUIInteraction(player.playernum)->selectedItem ) | |||
| 25760 | { | |||
| 25761 | const real_t fpsScale = getFPSScale(144.0); | |||
| 25762 | real_t setpointDiffX = fpsScale * std::max(.05, (1.0 - selectedItemAnimate.animateX)) / (5); | |||
| 25763 | real_t setpointDiffY = fpsScale * std::max(.05, (1.0 - selectedItemAnimate.animateY)) / (5); | |||
| 25764 | selectedItemAnimate.animateX += setpointDiffX; | |||
| 25765 | selectedItemAnimate.animateY += setpointDiffY; | |||
| 25766 | selectedItemAnimate.animateX = std::min(1.0, selectedItemAnimate.animateX); | |||
| 25767 | selectedItemAnimate.animateY = std::min(1.0, selectedItemAnimate.animateY); | |||
| 25768 | } | |||
| 25769 | else | |||
| 25770 | { | |||
| 25771 | selectedItemAnimate.animateX = 0.0; | |||
| 25772 | selectedItemAnimate.animateY = 0.0; | |||
| 25773 | } | |||
| 25774 | } | |||
| 25775 | ||||
| 25776 | void Player::Inventory_t::updateInventoryItemTooltip() | |||
| 25777 | { | |||
| 25778 | if ( !tooltipFrame || !frame || !titleOnlyTooltipFrame ) | |||
| 25779 | { | |||
| 25780 | return; | |||
| 25781 | } | |||
| 25782 | ||||
| 25783 | auto& tooltipDisplay = this->itemTooltipDisplay; | |||
| 25784 | ||||
| 25785 | if ( static_cast<int>(tooltipFrame->getOpacity()) != tooltipDisplay.opacitySetpoint ) | |||
| 25786 | { | |||
| 25787 | const real_t fpsScale = getFPSScale(144.0); | |||
| 25788 | if ( tooltipDisplay.opacitySetpoint == 0 ) | |||
| 25789 | { | |||
| 25790 | real_t setpointDiff = fpsScale * std::max(.05, (tooltipDisplay.opacityAnimate)) / (5); | |||
| 25791 | tooltipDisplay.opacityAnimate -= setpointDiff; | |||
| 25792 | tooltipDisplay.opacityAnimate = std::max(0.0, tooltipDisplay.opacityAnimate); | |||
| 25793 | } | |||
| 25794 | else | |||
| 25795 | { | |||
| 25796 | real_t setpointDiff = fpsScale * std::max(.05, (1.0 - tooltipDisplay.opacityAnimate)) / (1); | |||
| 25797 | tooltipDisplay.opacityAnimate += setpointDiff; | |||
| 25798 | tooltipDisplay.opacityAnimate = std::min(1.0, tooltipDisplay.opacityAnimate); | |||
| 25799 | } | |||
| 25800 | tooltipFrame->setOpacity(tooltipDisplay.opacityAnimate * 100); | |||
| 25801 | } | |||
| 25802 | else | |||
| 25803 | { | |||
| 25804 | tooltipFrame->setOpacity(tooltipDisplay.opacitySetpoint); | |||
| 25805 | } | |||
| 25806 | ||||
| 25807 | if ( static_cast<int>(titleOnlyTooltipFrame->getOpacity()) != tooltipDisplay.titleOnlyOpacitySetpoint ) | |||
| 25808 | { | |||
| 25809 | const real_t fpsScale = getFPSScale(144.0); | |||
| 25810 | if ( tooltipDisplay.titleOnlyOpacitySetpoint == 0 ) | |||
| 25811 | { | |||
| 25812 | real_t setpointDiff = fpsScale * std::max(.05, (tooltipDisplay.titleOnlyOpacityAnimate)) / (5); | |||
| 25813 | tooltipDisplay.titleOnlyOpacityAnimate -= setpointDiff; | |||
| 25814 | tooltipDisplay.titleOnlyOpacityAnimate = std::max(0.0, tooltipDisplay.titleOnlyOpacityAnimate); | |||
| 25815 | } | |||
| 25816 | else | |||
| 25817 | { | |||
| 25818 | real_t setpointDiff = fpsScale * std::max(.05, (1.0 - tooltipDisplay.titleOnlyOpacityAnimate)) / (1); | |||
| 25819 | tooltipDisplay.titleOnlyOpacityAnimate += setpointDiff; | |||
| 25820 | tooltipDisplay.titleOnlyOpacityAnimate = std::min(1.0, tooltipDisplay.titleOnlyOpacityAnimate); | |||
| 25821 | } | |||
| 25822 | titleOnlyTooltipFrame->setOpacity(tooltipDisplay.titleOnlyOpacityAnimate * 100); | |||
| 25823 | } | |||
| 25824 | else | |||
| 25825 | { | |||
| 25826 | titleOnlyTooltipFrame->setOpacity(tooltipDisplay.titleOnlyOpacitySetpoint); | |||
| 25827 | } | |||
| 25828 | ||||
| 25829 | if ( tooltipPromptFrame ) | |||
| 25830 | { | |||
| 25831 | tooltipPromptFrame->setOpacity(tooltipFrame->getOpacity()); | |||
| 25832 | } | |||
| 25833 | ||||
| 25834 | tooltipDisplay.expandSetpoint = tooltipDisplay.expanded ? 100 : 0; | |||
| 25835 | if ( static_cast<int>(tooltipDisplay.expandCurrent * 100) != tooltipDisplay.expandSetpoint ) | |||
| 25836 | { | |||
| 25837 | const real_t fpsScale = getFPSScale(144.0); | |||
| 25838 | if ( tooltipDisplay.expandSetpoint == 0 ) | |||
| 25839 | { | |||
| 25840 | //real_t setpointDiff = fpsScale * std::max(.05, (tooltipDisplay.expandAnimate) / 50); | |||
| 25841 | //tooltipDisplay.expandAnimate -= setpointDiff; | |||
| 25842 | tooltipDisplay.expandAnimate -= 2 * fpsScale / 100.0; | |||
| 25843 | tooltipDisplay.expandAnimate = std::max(0.0, tooltipDisplay.expandAnimate); | |||
| 25844 | } | |||
| 25845 | else | |||
| 25846 | { | |||
| 25847 | //real_t setpointDiff = fpsScale * std::max(.05, (1.0 - tooltipDisplay.expandAnimate) / 50); | |||
| 25848 | //tooltipDisplay.expandAnimate += setpointDiff; | |||
| 25849 | tooltipDisplay.expandAnimate += 2 * fpsScale / 100.0; | |||
| 25850 | tooltipDisplay.expandAnimate = std::min(1.0, tooltipDisplay.expandAnimate); | |||
| 25851 | } | |||
| 25852 | double t = tooltipDisplay.expandAnimate; | |||
| 25853 | tooltipDisplay.expandCurrent = t * t * (3.0f - 2.0f * t); // bezier from 0 to width as t (0-1); | |||
| 25854 | } | |||
| 25855 | else | |||
| 25856 | { | |||
| 25857 | tooltipDisplay.expandCurrent = tooltipDisplay.expandSetpoint / 100.0; | |||
| 25858 | } | |||
| 25859 | } | |||
| 25860 | ||||
| 25861 | void Player::Inventory_t::ItemTooltipDisplay_t::updateItem(const int player, Item* newItem) | |||
| 25862 | { | |||
| 25863 | if ( newItem && player >= 0 && player < MAXPLAYERS4 && stats[player] ) | |||
| 25864 | { | |||
| 25865 | uid = newItem->uid; | |||
| 25866 | type = newItem->type; | |||
| 25867 | status = newItem->status; | |||
| 25868 | beatitude = newItem->beatitude; | |||
| 25869 | count = newItem->count; | |||
| 25870 | appearance = newItem->appearance; | |||
| 25871 | identified = newItem->identified; | |||
| 25872 | ||||
| 25873 | if ( players[player]->inventoryUI.appraisal.current_item == uid ) | |||
| 25874 | { | |||
| 25875 | wasAppraisalTarget = true; | |||
| 25876 | } | |||
| 25877 | else | |||
| 25878 | { | |||
| 25879 | wasAppraisalTarget = false; | |||
| 25880 | } | |||
| 25881 | if ( stats[player] ) | |||
| 25882 | { | |||
| 25883 | playernum = player; | |||
| 25884 | playerLVL = stats[player]->LVL; | |||
| 25885 | playerEXP = stats[player]->EXP; | |||
| 25886 | playerSTR = statGetSTR(stats[player], players[player]->entity); | |||
| 25887 | playerDEX = statGetDEX(stats[player], players[player]->entity); | |||
| 25888 | playerCON = statGetCON(stats[player], players[player]->entity); | |||
| 25889 | playerINT = statGetINT(stats[player], players[player]->entity); | |||
| 25890 | playerPER = statGetPER(stats[player], players[player]->entity); | |||
| 25891 | playerCHR = statGetCHR(stats[player], players[player]->entity); | |||
| 25892 | } | |||
| 25893 | } | |||
| 25894 | } | |||
| 25895 | ||||
| 25896 | bool Player::Inventory_t::ItemTooltipDisplay_t::isItemSameAsCurrent(const int player, Item* newItem) | |||
| 25897 | { | |||
| 25898 | if ( newItem && player >= 0 && player < MAXPLAYERS4 && stats[player] ) | |||
| 25899 | { | |||
| 25900 | bool appraisingThisItem = false; | |||
| 25901 | if ( players[player]->inventoryUI.appraisal.current_item == uid ) | |||
| 25902 | { | |||
| 25903 | appraisingThisItem = true; | |||
| 25904 | } | |||
| 25905 | ||||
| 25906 | if ( newItem->uid == uid | |||
| 25907 | && newItem->type == type | |||
| 25908 | && newItem->status == status | |||
| 25909 | && newItem->beatitude == beatitude | |||
| 25910 | && newItem->count == count | |||
| 25911 | && newItem->appearance == appearance | |||
| 25912 | && newItem->identified == identified | |||
| 25913 | && (wasAppraisalTarget == appraisingThisItem) | |||
| 25914 | && playernum == player | |||
| 25915 | && playerLVL == stats[player]->LVL | |||
| 25916 | && playerEXP == stats[player]->EXP | |||
| 25917 | && playerSTR == statGetSTR(stats[player], players[player]->entity) | |||
| 25918 | && playerDEX == statGetDEX(stats[player], players[player]->entity) | |||
| 25919 | && playerCON == statGetCON(stats[player], players[player]->entity) | |||
| 25920 | && playerINT == statGetINT(stats[player], players[player]->entity) | |||
| 25921 | && playerPER == statGetPER(stats[player], players[player]->entity) | |||
| 25922 | && playerCHR == statGetCHR(stats[player], players[player]->entity) | |||
| 25923 | ) | |||
| 25924 | { | |||
| 25925 | return true; | |||
| 25926 | } | |||
| 25927 | } | |||
| 25928 | return false; | |||
| 25929 | } | |||
| 25930 | ||||
| 25931 | Player::Inventory_t::ItemTooltipDisplay_t::ItemTooltipDisplay_t() | |||
| 25932 | { | |||
| 25933 | uid = 0; | |||
| 25934 | type = WOODEN_SHIELD; | |||
| 25935 | status = BROKEN; | |||
| 25936 | beatitude = 0; | |||
| 25937 | count = 0; | |||
| 25938 | appearance = 0; | |||
| 25939 | identified = false; | |||
| 25940 | wasAppraisalTarget = false; | |||
| 25941 | playernum = -1; | |||
| 25942 | playerLVL = 0; | |||
| 25943 | playerEXP = 0; | |||
| 25944 | playerSTR = 0; | |||
| 25945 | playerDEX = 0; | |||
| 25946 | playerCON = 0; | |||
| 25947 | playerINT = 0; | |||
| 25948 | playerPER = 0; | |||
| 25949 | playerCHR = 0; | |||
| 25950 | } | |||
| 25951 | ||||
| 25952 | void Player::Inventory_t::updateItemContextMenuClickFrame() | |||
| 25953 | { | |||
| 25954 | if ( !interactBlockClickFrame ) | |||
| 25955 | { | |||
| 25956 | char interactBlockClickName[64] = ""; | |||
| 25957 | snprintf(interactBlockClickName, sizeof(interactBlockClickName), "player inventory dropdown block click %d", player.playernum); | |||
| 25958 | if ( interactBlockClickFrame = gameUIFrame[player.playernum]->addFrame(interactBlockClickName) ) | |||
| 25959 | { | |||
| 25960 | interactBlockClickFrame->setSize(SDL_Rect{ player.camera_virtualx1(), | |||
| 25961 | player.camera_virtualy1(), | |||
| 25962 | player.camera_virtualWidth(), | |||
| 25963 | player.camera_virtualHeight() }); | |||
| 25964 | interactBlockClickFrame->setOwner(player.playernum); | |||
| 25965 | interactBlockClickFrame->setDisabled(true); | |||
| 25966 | interactBlockClickFrame->setHollow(true); | |||
| 25967 | } | |||
| 25968 | } | |||
| 25969 | ||||
| 25970 | interactBlockClickFrame->setSize(SDL_Rect{ player.camera_virtualx1(), | |||
| 25971 | player.camera_virtualy1(), | |||
| 25972 | player.camera_virtualWidth(), | |||
| 25973 | player.camera_virtualHeight() }); | |||
| 25974 | ||||
| 25975 | if ( interactFrame ) | |||
| 25976 | { | |||
| 25977 | if ( interactFrame->isDisabled() ) | |||
| 25978 | { | |||
| 25979 | interactBlockClickFrame->setDisabled(true); | |||
| 25980 | interactBlockClickFrame->setHollow(true); | |||
| 25981 | } | |||
| 25982 | else | |||
| 25983 | { | |||
| 25984 | interactBlockClickFrame->setDisabled(false); | |||
| 25985 | interactBlockClickFrame->setHollow(false); | |||
| 25986 | } | |||
| 25987 | } | |||
| 25988 | } | |||
| 25989 | ||||
| 25990 | void Player::Inventory_t::updateCursor() | |||
| 25991 | { | |||
| 25992 | if ( !frame ) | |||
| 25993 | { | |||
| 25994 | return; | |||
| 25995 | } | |||
| 25996 | ||||
| 25997 | if ( !player.isLocalPlayer() ) | |||
| 25998 | { | |||
| 25999 | return; | |||
| 26000 | } | |||
| 26001 | ||||
| 26002 | if ( cursor.queuedModule != Player::GUI_t::MODULE_NONE | |||
| 26003 | && !player.shootmode && !nohud ) | |||
| 26004 | { | |||
| 26005 | int cursorWidth = player.inventoryUI.getSlotSize(); | |||
| 26006 | int cursorHeight = player.inventoryUI.getSlotSize(); | |||
| 26007 | bool moveMouse = false; | |||
| 26008 | auto queuedModule = cursor.queuedModule; | |||
| 26009 | if ( cursor.queuedModule == Player::GUI_t::MODULE_INVENTORY ) | |||
| 26010 | { | |||
| 26011 | if ( frame->isDisabled() || player.inventory_mode != INVENTORY_MODE_ITEM ) | |||
| 26012 | { | |||
| 26013 | // cancel | |||
| 26014 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26015 | } | |||
| 26016 | else if ( isInteractable ) | |||
| 26017 | { | |||
| 26018 | moveMouse = true; | |||
| 26019 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26020 | } | |||
| 26021 | } | |||
| 26022 | else if ( cursor.queuedModule == Player::GUI_t::MODULE_HOTBAR ) | |||
| 26023 | { | |||
| 26024 | if ( player.hotbar.hotbarFrame && player.hotbar.hotbarFrame->isDisabled() ) | |||
| 26025 | { | |||
| 26026 | // cancel | |||
| 26027 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26028 | } | |||
| 26029 | else if ( player.hotbar.isInteractable ) | |||
| 26030 | { | |||
| 26031 | moveMouse = true; | |||
| 26032 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26033 | } | |||
| 26034 | } | |||
| 26035 | else if ( cursor.queuedModule == Player::GUI_t::MODULE_SPELLS ) | |||
| 26036 | { | |||
| 26037 | if ( spellFrame->isDisabled() || player.inventory_mode != INVENTORY_MODE_SPELL ) | |||
| 26038 | { | |||
| 26039 | // cancel | |||
| 26040 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26041 | } | |||
| 26042 | else if ( spellPanel.isInteractable ) | |||
| 26043 | { | |||
| 26044 | moveMouse = true; | |||
| 26045 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26046 | } | |||
| 26047 | } | |||
| 26048 | else if ( cursor.queuedModule == Player::GUI_t::MODULE_CHEST ) | |||
| 26049 | { | |||
| 26050 | if ( !chestFrame | |||
| 26051 | || chestFrame->isDisabled() | |||
| 26052 | || player.inventory_mode != INVENTORY_MODE_ITEM | |||
| 26053 | || !openedChest[player.playernum] ) | |||
| 26054 | { | |||
| 26055 | // cancel | |||
| 26056 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26057 | } | |||
| 26058 | else if ( chestGUI.isInteractable ) | |||
| 26059 | { | |||
| 26060 | moveMouse = true; | |||
| 26061 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26062 | } | |||
| 26063 | } | |||
| 26064 | else if ( cursor.queuedModule == Player::GUI_t::MODULE_SHOP ) | |||
| 26065 | { | |||
| 26066 | auto& shopGUI = player.shopGUI; | |||
| 26067 | if ( !shopGUI.shopFrame | |||
| 26068 | || shopGUI.shopFrame->isDisabled() | |||
| 26069 | || player.inventory_mode != INVENTORY_MODE_ITEM | |||
| 26070 | || !shopGUI.bOpen ) | |||
| 26071 | { | |||
| 26072 | // cancel | |||
| 26073 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26074 | } | |||
| 26075 | else if ( shopGUI.isInteractable ) | |||
| 26076 | { | |||
| 26077 | moveMouse = true; | |||
| 26078 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26079 | } | |||
| 26080 | } | |||
| 26081 | else if ( cursor.queuedModule == Player::GUI_t::MODULE_TINKERING ) | |||
| 26082 | { | |||
| 26083 | auto& tinkerGUI = GenericGUI[player.playernum].tinkerGUI; | |||
| 26084 | if ( !tinkerGUI.tinkerGUIHasBeenCreated() | |||
| 26085 | || tinkerGUI.tinkerFrame->isDisabled() | |||
| 26086 | || !tinkerGUI.isConstructMenuActive() ) | |||
| 26087 | { | |||
| 26088 | // cancel | |||
| 26089 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26090 | } | |||
| 26091 | else if ( tinkerGUI.isInteractable ) | |||
| 26092 | { | |||
| 26093 | moveMouse = true; | |||
| 26094 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26095 | } | |||
| 26096 | if ( cursor.queuedFrameToWarpTo ) | |||
| 26097 | { | |||
| 26098 | cursorWidth = cursor.queuedFrameToWarpTo->getSize().w; | |||
| 26099 | cursorHeight = cursor.queuedFrameToWarpTo->getSize().h; | |||
| 26100 | } | |||
| 26101 | } | |||
| 26102 | else if ( cursor.queuedModule == Player::GUI_t::MODULE_ALCHEMY ) | |||
| 26103 | { | |||
| 26104 | auto& alchemyGUI = GenericGUI[player.playernum].alchemyGUI; | |||
| 26105 | if ( !alchemyGUI.alchemyGUIHasBeenCreated() | |||
| 26106 | || alchemyGUI.alchFrame->isDisabled() ) | |||
| 26107 | { | |||
| 26108 | // cancel | |||
| 26109 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26110 | } | |||
| 26111 | else if ( alchemyGUI.isInteractable ) | |||
| 26112 | { | |||
| 26113 | moveMouse = true; | |||
| 26114 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26115 | } | |||
| 26116 | } | |||
| 26117 | else if ( cursor.queuedModule == Player::GUI_t::MODULE_FEATHER ) | |||
| 26118 | { | |||
| 26119 | auto& featherGUI = GenericGUI[player.playernum].featherGUI; | |||
| 26120 | if ( !featherGUI.featherGUIHasBeenCreated() | |||
| 26121 | || featherGUI.featherFrame->isDisabled() ) | |||
| 26122 | { | |||
| 26123 | // cancel | |||
| 26124 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26125 | } | |||
| 26126 | else if ( featherGUI.isInteractable ) | |||
| 26127 | { | |||
| 26128 | moveMouse = true; | |||
| 26129 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26130 | } | |||
| 26131 | if ( cursor.queuedFrameToWarpTo ) | |||
| 26132 | { | |||
| 26133 | cursorWidth = cursor.queuedFrameToWarpTo->getSize().w; | |||
| 26134 | cursorHeight = cursor.queuedFrameToWarpTo->getSize().h; | |||
| 26135 | } | |||
| 26136 | } | |||
| 26137 | ||||
| 26138 | if ( moveMouse && cursor.queuedFrameToWarpTo ) | |||
| 26139 | { | |||
| 26140 | //messagePlayer(0, "Queue warp: %d", queuedModule); | |||
| 26141 | cursor.queuedFrameToWarpTo->warpMouseToFrame(player.playernum, (Inputs::SET_CONTROLLER)); | |||
| 26142 | SDL_Rect pos = cursor.queuedFrameToWarpTo->getAbsoluteSize(); | |||
| 26143 | pos.x -= player.camera_virtualx1(); // offset any splitscreen camera positioning | |||
| 26144 | pos.y -= player.camera_virtualy1(); | |||
| 26145 | player.inventoryUI.updateSelectedSlotAnimation(pos.x, pos.y, | |||
| 26146 | cursorWidth, cursorHeight, false); | |||
| 26147 | cursor.queuedFrameToWarpTo = nullptr; | |||
| 26148 | } | |||
| 26149 | else if ( cursor.queuedFrameToWarpTo && cursor.queuedModule == Player::GUI_t::MODULE_NONE ) | |||
| 26150 | { | |||
| 26151 | //messagePlayer(0, "Queue cancel: %d", queuedModule); | |||
| 26152 | } | |||
| 26153 | else if ( cursor.queuedFrameToWarpTo ) | |||
| 26154 | { | |||
| 26155 | //selectedItemCursorFrame->setDisabled(false); // show the cursor while we wait | |||
| 26156 | } | |||
| 26157 | } | |||
| 26158 | else | |||
| 26159 | { | |||
| 26160 | cursor.queuedFrameToWarpTo = nullptr; | |||
| 26161 | cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 26162 | } | |||
| 26163 | ||||
| 26164 | if ( auto oldSelectedSlotCursor = frame->findFrame("inventory old item cursor") ) | |||
| 26165 | { | |||
| 26166 | if ( auto oldSelectedFrame = frame->findFrame("inventory old selected item") ) | |||
| 26167 | { | |||
| 26168 | oldSelectedSlotCursor->setDisabled(oldSelectedFrame->isDisabled()); | |||
| 26169 | ||||
| 26170 | if ( player.hotbar.hotbarFrame ) | |||
| 26171 | { | |||
| 26172 | if ( auto highlight = oldSelectedFrame->findImage("inventory old selected highlight") ) | |||
| 26173 | { | |||
| 26174 | highlight->disabled = false; | |||
| 26175 | if ( auto oldHotbarSelectedFrame = player.hotbar.hotbarFrame->findFrame("hotbar old selected item") ) | |||
| 26176 | { | |||
| 26177 | if ( !oldHotbarSelectedFrame->isDisabled() ) | |||
| 26178 | { | |||
| 26179 | oldSelectedSlotCursor->setDisabled(true); | |||
| 26180 | highlight->disabled = true; | |||
| 26181 | } | |||
| 26182 | } | |||
| 26183 | } | |||
| 26184 | } | |||
| 26185 | ||||
| 26186 | if ( !oldSelectedSlotCursor->isDisabled() ) | |||
| 26187 | { | |||
| 26188 | SDL_Rect cursorSize = oldSelectedSlotCursor->getSize(); | |||
| 26189 | cursorSize.x = (oldSelectedFrame->getSize().x - 1) - cursor.cursorToSlotOffset; | |||
| 26190 | cursorSize.y = (oldSelectedFrame->getSize().y - 1) - cursor.cursorToSlotOffset; | |||
| 26191 | oldSelectedSlotCursor->setSize(cursorSize); | |||
| 26192 | ||||
| 26193 | int offset = 8;// ((ticks - cursor.lastUpdateTick) % 50 < 25) ? largeOffset : smallOffset; | |||
| 26194 | ||||
| 26195 | Uint8 r, g, b, a; | |||
| 26196 | if ( auto tl = oldSelectedSlotCursor->findImage("inventory old cursor topleft") ) | |||
| 26197 | { | |||
| 26198 | tl->pos = SDL_Rect{ offset, offset, tl->pos.w, tl->pos.h }; | |||
| 26199 | getColor(tl->color, &r, &g, &b, &a); | |||
| 26200 | a = oldSelectedCursorOpacity; | |||
| 26201 | tl->color = makeColor( r, g, b, a); | |||
| 26202 | } | |||
| 26203 | if ( auto tr = oldSelectedSlotCursor->findImage("inventory old cursor topright") ) | |||
| 26204 | { | |||
| 26205 | tr->pos = SDL_Rect{ -offset + cursorSize.w - tr->pos.w, offset, tr->pos.w, tr->pos.h }; | |||
| 26206 | tr->color = makeColor( r, g, b, a); | |||
| 26207 | } | |||
| 26208 | if ( auto bl = oldSelectedSlotCursor->findImage("inventory old cursor bottomleft") ) | |||
| 26209 | { | |||
| 26210 | bl->pos = SDL_Rect{ offset, -offset + cursorSize.h - bl->pos.h, bl->pos.w, bl->pos.h }; | |||
| 26211 | bl->color = makeColor( r, g, b, a); | |||
| 26212 | } | |||
| 26213 | if ( auto br = oldSelectedSlotCursor->findImage("inventory old cursor bottomright") ) | |||
| 26214 | { | |||
| 26215 | br->pos = SDL_Rect{ -offset + cursorSize.w - br->pos.w, -offset + cursorSize.h - br->pos.h, br->pos.w, br->pos.h }; | |||
| 26216 | br->color = makeColor( r, g, b, a); | |||
| 26217 | } | |||
| 26218 | } | |||
| 26219 | } | |||
| 26220 | } | |||
| 26221 | ||||
| 26222 | if ( selectedItemCursorFrame ) | |||
| 26223 | { | |||
| 26224 | SDL_Rect cursorSize = selectedItemCursorFrame->getSize(); | |||
| 26225 | ||||
| 26226 | const int smallOffset = 2; | |||
| 26227 | const int largeOffset = 4; | |||
| 26228 | ||||
| 26229 | int offset = ((ticks - cursor.lastUpdateTick) % TICKS_PER_SECOND50 < TICKS_PER_SECOND50 / 2) ? largeOffset : smallOffset; | |||
| 26230 | if ( inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 26231 | { | |||
| 26232 | if ( inputs.getUIInteraction(player.playernum)->selectedItem | |||
| 26233 | || inputs.getUIInteraction(player.playernum)->itemMenuOpen ) | |||
| 26234 | { | |||
| 26235 | // animate cursor | |||
| 26236 | } | |||
| 26237 | else | |||
| 26238 | { | |||
| 26239 | offset = smallOffset; // don't animate while mouse normal hovering | |||
| 26240 | } | |||
| 26241 | } | |||
| 26242 | ||||
| 26243 | Uint8 r, g, b, a; | |||
| 26244 | if ( auto tl = selectedItemCursorFrame->findImage("inventory selected cursor topleft") ) | |||
| 26245 | { | |||
| 26246 | tl->pos = SDL_Rect{ offset, offset, tl->pos.w, tl->pos.h }; | |||
| 26247 | getColor(tl->color, &r, &g, &b, &a); | |||
| 26248 | a = selectedCursorOpacity; | |||
| 26249 | tl->color = makeColor( r, g, b, a); | |||
| 26250 | } | |||
| 26251 | if ( auto tr = selectedItemCursorFrame->findImage("inventory selected cursor topright") ) | |||
| 26252 | { | |||
| 26253 | tr->pos = SDL_Rect{ -offset + cursorSize.w - tr->pos.w, offset, tr->pos.w, tr->pos.h }; | |||
| 26254 | tr->color = makeColor( r, g, b, a); | |||
| 26255 | } | |||
| 26256 | if ( auto bl = selectedItemCursorFrame->findImage("inventory selected cursor bottomleft") ) | |||
| 26257 | { | |||
| 26258 | bl->pos = SDL_Rect{ offset, -offset + cursorSize.h - bl->pos.h, bl->pos.w, bl->pos.h }; | |||
| 26259 | bl->color = makeColor( r, g, b, a); | |||
| 26260 | } | |||
| 26261 | if ( auto br = selectedItemCursorFrame->findImage("inventory selected cursor bottomright") ) | |||
| 26262 | { | |||
| 26263 | br->pos = SDL_Rect{ -offset + cursorSize.w - br->pos.w, -offset + cursorSize.h - br->pos.h, br->pos.w, br->pos.h }; | |||
| 26264 | br->color = makeColor( r, g, b, a); | |||
| 26265 | } | |||
| 26266 | ||||
| 26267 | SDL_Rect currentPos = selectedItemCursorFrame->getSize(); | |||
| 26268 | const int offsetPosition = cursor.cursorToSlotOffset; | |||
| 26269 | if ( cursor.animateSetpointX - offsetPosition != currentPos.x | |||
| 26270 | || cursor.animateSetpointY - offsetPosition != currentPos.y ) | |||
| 26271 | { | |||
| 26272 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 26273 | real_t setpointDiffX = fpsScale * std::max(.1, (1.0 - cursor.animateX)) / (2.5); | |||
| 26274 | real_t setpointDiffY = fpsScale * std::max(.1, (1.0 - cursor.animateY)) / (2.5); | |||
| 26275 | cursor.animateX += setpointDiffX; | |||
| 26276 | cursor.animateY += setpointDiffY; | |||
| 26277 | cursor.animateX = std::min(1.0, cursor.animateX); | |||
| 26278 | cursor.animateY = std::min(1.0, cursor.animateY); | |||
| 26279 | ||||
| 26280 | int destX = cursor.animateSetpointX - cursor.animateStartX - offsetPosition; | |||
| 26281 | int destY = cursor.animateSetpointY - cursor.animateStartY - offsetPosition; | |||
| 26282 | ||||
| 26283 | currentPos.x = cursor.animateStartX + destX * cursor.animateX; | |||
| 26284 | currentPos.y = cursor.animateStartY + destY * cursor.animateY; | |||
| 26285 | selectedItemCursorFrame->setSize(currentPos); | |||
| 26286 | //messagePlayer(0, "%.2f | %.2f", inventory_t.selectedSlotAnimateX, setpointDiffX); | |||
| 26287 | } | |||
| 26288 | } | |||
| 26289 | } | |||
| 26290 | ||||
| 26291 | void Player::HUD_t::updateCursorAnimation(int destx, int desty, int width, int height, bool usingMouse) | |||
| 26292 | { | |||
| 26293 | if ( cursorFrame ) | |||
| 26294 | { | |||
| 26295 | if ( auto hudCursor = cursorFrame->findFrame("hud cursor") ) | |||
| 26296 | { | |||
| 26297 | if ( usingMouse ) | |||
| 26298 | { | |||
| 26299 | hudCursor->setSize( | |||
| 26300 | SDL_Rect{ | |||
| 26301 | destx - cursor.cursorToSlotOffset, | |||
| 26302 | desty - cursor.cursorToSlotOffset, | |||
| 26303 | width + 2 * (cursor.cursorToSlotOffset + 1), | |||
| 26304 | height + 2 * (cursor.cursorToSlotOffset + 1) | |||
| 26305 | } | |||
| 26306 | ); | |||
| 26307 | cursor.animateSetpointX = destx; | |||
| 26308 | cursor.animateSetpointY = desty; | |||
| 26309 | cursor.animateSetpointW = width + 2 * (cursor.cursorToSlotOffset + 1); | |||
| 26310 | cursor.animateSetpointH = height + 2 * (cursor.cursorToSlotOffset + 1); | |||
| 26311 | ||||
| 26312 | cursor.animateStartX = destx; | |||
| 26313 | cursor.animateStartY = desty; | |||
| 26314 | cursor.animateStartW = width + 2 * (cursor.cursorToSlotOffset + 1); | |||
| 26315 | cursor.animateStartH = height + 2 * (cursor.cursorToSlotOffset + 1); | |||
| 26316 | } | |||
| 26317 | else if ( cursor.animateSetpointX != destx | |||
| 26318 | || cursor.animateSetpointY != desty | |||
| 26319 | || cursor.animateSetpointW != width + 2 * (cursor.cursorToSlotOffset + 1) | |||
| 26320 | || cursor.animateSetpointH != height + 2 * (cursor.cursorToSlotOffset + 1) ) | |||
| 26321 | { | |||
| 26322 | SDL_Rect size = hudCursor->getSize(); | |||
| 26323 | cursor.animateStartX = size.x; | |||
| 26324 | cursor.animateStartY = size.y; | |||
| 26325 | cursor.animateStartW = size.w; | |||
| 26326 | cursor.animateStartH = size.h; | |||
| 26327 | ||||
| 26328 | hudCursor->setSize(size); | |||
| 26329 | cursor.animateSetpointX = destx; | |||
| 26330 | cursor.animateSetpointY = desty; | |||
| 26331 | cursor.animateSetpointW = width + 2 * (cursor.cursorToSlotOffset + 1); | |||
| 26332 | cursor.animateSetpointH = height + 2 * (cursor.cursorToSlotOffset + 1); | |||
| 26333 | ||||
| 26334 | cursor.animateX = 0.0; | |||
| 26335 | cursor.animateY = 0.0; | |||
| 26336 | cursor.animateW = 0.0; | |||
| 26337 | cursor.animateH = 0.0; | |||
| 26338 | ||||
| 26339 | cursor.lastUpdateTick = ticks; | |||
| 26340 | } | |||
| 26341 | } | |||
| 26342 | } | |||
| 26343 | } | |||
| 26344 | ||||
| 26345 | void Player::HUD_t::updateCursor() | |||
| 26346 | { | |||
| 26347 | if ( !cursorFrame ) | |||
| 26348 | { | |||
| 26349 | char name[32]; | |||
| 26350 | snprintf(name, sizeof(name), "player hud cursor %d", player.playernum); | |||
| 26351 | cursorFrame = gameUIFrame[player.playernum]->addFrame(name); | |||
| 26352 | cursorFrame->setHollow(true); | |||
| 26353 | cursorFrame->setBorder(0); | |||
| 26354 | cursorFrame->setOwner(player.playernum); | |||
| 26355 | ||||
| 26356 | auto cursor = cursorFrame->addFrame("hud cursor"); | |||
| 26357 | cursor->setHollow(true); | |||
| 26358 | cursor->setSize(SDL_Rect{ 0, 0, 0, 0 }); | |||
| 26359 | Uint32 color = makeColor( 255, 255, 255, selectedCursorOpacity); | |||
| 26360 | cursor->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 26361 | color, "*#images/ui/Inventory/Selector_TL.png", "hud cursor topleft"); | |||
| 26362 | cursor->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 26363 | color, "*#images/ui/Inventory/Selector_TR.png", "hud cursor topright"); | |||
| 26364 | cursor->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 26365 | color, "*#images/ui/Inventory/Selector_BL.png", "hud cursor bottomleft"); | |||
| 26366 | cursor->addImage(SDL_Rect{ 0, 0, 14, 14 }, | |||
| 26367 | color, "*#images/ui/Inventory/Selector_BR.png", "hud cursor bottomright"); | |||
| 26368 | } | |||
| 26369 | ||||
| 26370 | cursorFrame->setSize(SDL_Rect{ players[player.playernum]->camera_virtualx1(), | |||
| 26371 | players[player.playernum]->camera_virtualy1(), | |||
| 26372 | players[player.playernum]->camera_virtualWidth(), | |||
| 26373 | players[player.playernum]->camera_virtualHeight() }); | |||
| 26374 | ||||
| 26375 | if ( !players[player.playernum]->isLocalPlayer() | |||
| 26376 | || players[player.playernum]->shootmode | |||
| 26377 | || players[player.playernum]->GUI.bActiveModuleUsesInventory() | |||
| 26378 | || players[player.playernum]->GUI.bActiveModuleHasNoCursor() ) | |||
| 26379 | { | |||
| 26380 | // hide | |||
| 26381 | cursorFrame->setDisabled(true); | |||
| 26382 | } | |||
| 26383 | else | |||
| 26384 | { | |||
| 26385 | cursorFrame->setDisabled(false); | |||
| 26386 | } | |||
| 26387 | ||||
| 26388 | if ( auto hudCursor = cursorFrame->findFrame("hud cursor") ) | |||
| 26389 | { | |||
| 26390 | SDL_Rect cursorSize = hudCursor->getSize(); | |||
| 26391 | const int smallOffset = 2; | |||
| 26392 | const int largeOffset = 4; | |||
| 26393 | ||||
| 26394 | int offset = ((ticks - cursor.lastUpdateTick) % TICKS_PER_SECOND50 < TICKS_PER_SECOND50 / 2) ? largeOffset : smallOffset; | |||
| 26395 | if ( inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 26396 | { | |||
| 26397 | if ( player.GUI.dropdownMenu.bOpen || player.GUI.activeModule == Player::GUI_t::MODULE_PORTRAIT ) | |||
| 26398 | { | |||
| 26399 | // animate cursor | |||
| 26400 | } | |||
| 26401 | else | |||
| 26402 | { | |||
| 26403 | offset = smallOffset; // don't animate while mouse normal hovering | |||
| 26404 | } | |||
| 26405 | } | |||
| 26406 | ||||
| 26407 | Uint8 r, g, b, a; | |||
| 26408 | if ( auto tl = hudCursor->findImage("hud cursor topleft") ) | |||
| 26409 | { | |||
| 26410 | tl->pos = SDL_Rect{ offset, offset, tl->pos.w, tl->pos.h }; | |||
| 26411 | getColor(tl->color, &r, &g, &b, &a); | |||
| 26412 | a = selectedCursorOpacity; | |||
| 26413 | tl->color = makeColor( r, g, b, a); | |||
| 26414 | } | |||
| 26415 | if ( auto tr = hudCursor->findImage("hud cursor topright") ) | |||
| 26416 | { | |||
| 26417 | tr->pos = SDL_Rect{ -offset + cursorSize.w - tr->pos.w, offset, tr->pos.w, tr->pos.h }; | |||
| 26418 | tr->color = makeColor( r, g, b, a); | |||
| 26419 | } | |||
| 26420 | if ( auto bl = hudCursor->findImage("hud cursor bottomleft") ) | |||
| 26421 | { | |||
| 26422 | bl->pos = SDL_Rect{ offset, -offset + cursorSize.h - bl->pos.h, bl->pos.w, bl->pos.h }; | |||
| 26423 | bl->color = makeColor( r, g, b, a); | |||
| 26424 | } | |||
| 26425 | if ( auto br = hudCursor->findImage("hud cursor bottomright") ) | |||
| 26426 | { | |||
| 26427 | br->pos = SDL_Rect{ -offset + cursorSize.w - br->pos.w, -offset + cursorSize.h - br->pos.h, br->pos.w, br->pos.h }; | |||
| 26428 | br->color = makeColor( r, g, b, a); | |||
| 26429 | } | |||
| 26430 | ||||
| 26431 | SDL_Rect currentPos = hudCursor->getSize(); | |||
| 26432 | const int offsetPosition = cursor.cursorToSlotOffset; | |||
| 26433 | if ( cursor.animateSetpointX - offsetPosition != currentPos.x | |||
| 26434 | || cursor.animateSetpointY - offsetPosition != currentPos.y | |||
| 26435 | || cursor.animateSetpointW != currentPos.w | |||
| 26436 | || cursor.animateSetpointH != currentPos.h ) | |||
| 26437 | { | |||
| 26438 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 26439 | real_t setpointDiffX = fpsScale * std::max(.1, (1.0 - cursor.animateX)) / (2.5); | |||
| 26440 | real_t setpointDiffY = fpsScale * std::max(.1, (1.0 - cursor.animateY)) / (2.5); | |||
| 26441 | real_t setpointDiffW = fpsScale * std::max(.1, (1.0 - cursor.animateW)) / (2.5); | |||
| 26442 | real_t setpointDiffH = fpsScale * std::max(.1, (1.0 - cursor.animateH)) / (2.5); | |||
| 26443 | cursor.animateX += setpointDiffX; | |||
| 26444 | cursor.animateY += setpointDiffY; | |||
| 26445 | cursor.animateX = std::min(1.0, cursor.animateX); | |||
| 26446 | cursor.animateY = std::min(1.0, cursor.animateY); | |||
| 26447 | cursor.animateW += setpointDiffW; | |||
| 26448 | cursor.animateH += setpointDiffH; | |||
| 26449 | cursor.animateW = std::min(1.0, cursor.animateW); | |||
| 26450 | cursor.animateH = std::min(1.0, cursor.animateH); | |||
| 26451 | ||||
| 26452 | int destX = cursor.animateSetpointX - cursor.animateStartX - offsetPosition; | |||
| 26453 | int destY = cursor.animateSetpointY - cursor.animateStartY - offsetPosition; | |||
| 26454 | int destW = cursor.animateSetpointW - cursor.animateStartW; | |||
| 26455 | int destH = cursor.animateSetpointH - cursor.animateStartH; | |||
| 26456 | ||||
| 26457 | currentPos.x = cursor.animateStartX + destX * cursor.animateX; | |||
| 26458 | currentPos.y = cursor.animateStartY + destY * cursor.animateY; | |||
| 26459 | currentPos.w = cursor.animateStartW + destW * cursor.animateW; | |||
| 26460 | currentPos.h = cursor.animateStartH + destH * cursor.animateH; | |||
| 26461 | hudCursor->setSize(currentPos); | |||
| 26462 | } | |||
| 26463 | } | |||
| 26464 | } | |||
| 26465 | ||||
| 26466 | void Player::Hotbar_t::updateCursor() | |||
| 26467 | { | |||
| 26468 | if ( !hotbarFrame ) | |||
| 26469 | { | |||
| 26470 | return; | |||
| 26471 | } | |||
| 26472 | ||||
| 26473 | if ( !player.isLocalPlayer() ) | |||
| 26474 | { | |||
| 26475 | return; | |||
| 26476 | } | |||
| 26477 | ||||
| 26478 | if ( auto oldSelectedSlotCursor = hotbarFrame->findFrame("hotbar old item cursor") ) | |||
| 26479 | { | |||
| 26480 | if ( auto oldSelectedFrame = hotbarFrame->findFrame("hotbar old selected item") ) | |||
| 26481 | { | |||
| 26482 | oldSelectedSlotCursor->setDisabled(oldSelectedFrame->isDisabled()); | |||
| 26483 | ||||
| 26484 | if ( !oldSelectedSlotCursor->isDisabled() ) | |||
| 26485 | { | |||
| 26486 | SDL_Rect cursorSize = oldSelectedSlotCursor->getSize(); | |||
| 26487 | cursorSize.x = (oldSelectedFrame->getSize().x - 1) - shootmodeCursor.cursorToSlotOffset; | |||
| 26488 | cursorSize.y = (oldSelectedFrame->getSize().y - 1) - shootmodeCursor.cursorToSlotOffset; | |||
| 26489 | oldSelectedSlotCursor->setSize(cursorSize); | |||
| 26490 | ||||
| 26491 | int offset = 8;// ((ticks - shootmodeCursor.lastUpdateTick) % TICKS_PER_SECOND < 25) ? largeOffset : smallOffset; | |||
| 26492 | ||||
| 26493 | Uint8 r, g, b, a; | |||
| 26494 | if ( auto tl = oldSelectedSlotCursor->findImage("hotbar old cursor topleft") ) | |||
| 26495 | { | |||
| 26496 | tl->pos = SDL_Rect{ offset, offset, tl->pos.w, tl->pos.h }; | |||
| 26497 | getColor(tl->color, &r, &g, &b, &a); | |||
| 26498 | a = oldSelectedCursorOpacity; | |||
| 26499 | tl->color = makeColor( r, g, b, a); | |||
| 26500 | } | |||
| 26501 | if ( auto tr = oldSelectedSlotCursor->findImage("hotbar old cursor topright") ) | |||
| 26502 | { | |||
| 26503 | tr->pos = SDL_Rect{ -offset + cursorSize.w - tr->pos.w, offset, tr->pos.w, tr->pos.h }; | |||
| 26504 | tr->color = makeColor( r, g, b, a); | |||
| 26505 | } | |||
| 26506 | if ( auto bl = oldSelectedSlotCursor->findImage("hotbar old cursor bottomleft") ) | |||
| 26507 | { | |||
| 26508 | bl->pos = SDL_Rect{ offset, -offset + cursorSize.h - bl->pos.h, bl->pos.w, bl->pos.h }; | |||
| 26509 | bl->color = makeColor( r, g, b, a); | |||
| 26510 | } | |||
| 26511 | if ( auto br = oldSelectedSlotCursor->findImage("hotbar old cursor bottomright") ) | |||
| 26512 | { | |||
| 26513 | br->pos = SDL_Rect{ -offset + cursorSize.w - br->pos.w, -offset + cursorSize.h - br->pos.h, br->pos.w, br->pos.h }; | |||
| 26514 | br->color = makeColor( r, g, b, a); | |||
| 26515 | } | |||
| 26516 | } | |||
| 26517 | } | |||
| 26518 | } | |||
| 26519 | ||||
| 26520 | if ( auto selectedSlotCursor = hotbarFrame->findFrame("shootmode selected item cursor") ) | |||
| 26521 | { | |||
| 26522 | SDL_Rect cursorSize = selectedSlotCursor->getSize(); | |||
| 26523 | ||||
| 26524 | const int smallOffset = 2; | |||
| 26525 | const int largeOffset = 4; | |||
| 26526 | ||||
| 26527 | int offset = ((ticks - shootmodeCursor.lastUpdateTick) % TICKS_PER_SECOND50 < TICKS_PER_SECOND50 / 2) ? largeOffset : smallOffset; | |||
| 26528 | if ( inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 26529 | { | |||
| 26530 | if ( inputs.getUIInteraction(player.playernum)->selectedItem ) | |||
| 26531 | { | |||
| 26532 | //offset = largeOffset; | |||
| 26533 | } | |||
| 26534 | else | |||
| 26535 | { | |||
| 26536 | offset = smallOffset; | |||
| 26537 | } | |||
| 26538 | } | |||
| 26539 | ||||
| 26540 | Uint8 r, g, b, a; | |||
| 26541 | if ( auto tl = selectedSlotCursor->findImage("shootmode selected cursor topleft") ) | |||
| 26542 | { | |||
| 26543 | tl->pos = SDL_Rect{ offset, offset, tl->pos.w, tl->pos.h }; | |||
| 26544 | getColor(tl->color, &r, &g, &b, &a); | |||
| 26545 | a = selectedCursorOpacity; | |||
| 26546 | tl->color = makeColor( r, g, b, a); | |||
| 26547 | } | |||
| 26548 | if ( auto tr = selectedSlotCursor->findImage("shootmode selected cursor topright") ) | |||
| 26549 | { | |||
| 26550 | tr->pos = SDL_Rect{ -offset + cursorSize.w - tr->pos.w, offset, tr->pos.w, tr->pos.h }; | |||
| 26551 | tr->color = makeColor( r, g, b, a); | |||
| 26552 | } | |||
| 26553 | if ( auto bl = selectedSlotCursor->findImage("shootmode selected cursor bottomleft") ) | |||
| 26554 | { | |||
| 26555 | bl->pos = SDL_Rect{ offset, -offset + cursorSize.h - bl->pos.h, bl->pos.w, bl->pos.h }; | |||
| 26556 | bl->color = makeColor( r, g, b, a); | |||
| 26557 | } | |||
| 26558 | if ( auto br = selectedSlotCursor->findImage("shootmode selected cursor bottomright") ) | |||
| 26559 | { | |||
| 26560 | br->pos = SDL_Rect{ -offset + cursorSize.w - br->pos.w, -offset + cursorSize.h - br->pos.h, br->pos.w, br->pos.h }; | |||
| 26561 | br->color = makeColor( r, g, b, a); | |||
| 26562 | } | |||
| 26563 | ||||
| 26564 | SDL_Rect currentPos = selectedSlotCursor->getSize(); | |||
| 26565 | const int offsetPosition = shootmodeCursor.cursorToSlotOffset; | |||
| 26566 | if ( shootmodeCursor.animateSetpointX - offsetPosition != currentPos.x | |||
| 26567 | || shootmodeCursor.animateSetpointY - offsetPosition != currentPos.y ) | |||
| 26568 | { | |||
| 26569 | auto& cursor = shootmodeCursor; | |||
| 26570 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 26571 | real_t setpointDiffX = fpsScale * std::max(.1, (1.0 - cursor.animateX)) / (2.5); | |||
| 26572 | real_t setpointDiffY = fpsScale * std::max(.1, (1.0 - cursor.animateY)) / (2.5); | |||
| 26573 | cursor.animateX += setpointDiffX; | |||
| 26574 | cursor.animateY += setpointDiffY; | |||
| 26575 | cursor.animateX = std::min(1.0, cursor.animateX); | |||
| 26576 | cursor.animateY = std::min(1.0, cursor.animateY); | |||
| 26577 | ||||
| 26578 | int destX = cursor.animateSetpointX - cursor.animateStartX - offsetPosition; | |||
| 26579 | int destY = cursor.animateSetpointY - cursor.animateStartY - offsetPosition; | |||
| 26580 | ||||
| 26581 | currentPos.x = cursor.animateStartX + destX * cursor.animateX; | |||
| 26582 | currentPos.y = cursor.animateStartY + destY * cursor.animateY; | |||
| 26583 | selectedSlotCursor->setSize(currentPos); | |||
| 26584 | //messagePlayer(0, "%.2f | %.2f", inventory_t.selectedSlotAnimateX, setpointDiffX); | |||
| 26585 | } | |||
| 26586 | } | |||
| 26587 | } | |||
| 26588 | ||||
| 26589 | void Player::Inventory_t::processInventory() | |||
| 26590 | { | |||
| 26591 | if ( !player.characterSheet.sheetFrame ) | |||
| 26592 | { | |||
| 26593 | player.characterSheet.createCharacterSheet(); | |||
| 26594 | } | |||
| 26595 | if ( !frame ) | |||
| 26596 | { | |||
| 26597 | createPlayerInventory(player.playernum); | |||
| 26598 | } | |||
| 26599 | if ( !tooltipFrame ) | |||
| 26600 | { | |||
| 26601 | createInventoryTooltipFrame(player.playernum); | |||
| 26602 | } | |||
| 26603 | ||||
| 26604 | frame->setSize(SDL_Rect{ players[player.playernum]->camera_virtualx1(), | |||
| 26605 | players[player.playernum]->camera_virtualy1(), | |||
| 26606 | players[player.playernum]->camera_virtualWidth(), | |||
| 26607 | players[player.playernum]->camera_virtualHeight()}); | |||
| 26608 | ||||
| 26609 | bool tooltipWasDisabled = tooltipFrame->isDisabled(); | |||
| 26610 | ||||
| 26611 | updateInventory(); | |||
| 26612 | ||||
| 26613 | player.shopGUI.updateShop(); | |||
| 26614 | ||||
| 26615 | if ( tooltipWasDisabled && !tooltipFrame->isDisabled() ) | |||
| 26616 | { | |||
| 26617 | tooltipFrame->setOpacity(0.0); | |||
| 26618 | } | |||
| 26619 | } | |||
| 26620 | ||||
| 26621 | void Player::HUD_t::resetBars() | |||
| 26622 | { | |||
| 26623 | xpInfo.cycleProcessedOnTick = 0; | |||
| 26624 | xpInfo.cycleStatus = XPInfo_t::CYCLE_NONE; | |||
| 26625 | xpInfo.cycleTicks = 0; | |||
| 26626 | xpInfo.fade = 1.0; | |||
| 26627 | xpInfo.fadeIn = true; | |||
| 26628 | if ( xpFrame ) | |||
| 26629 | { | |||
| 26630 | xpBar.animateSetpoint = std::min(100, stats[player.playernum]->EXP) * 10; | |||
| 26631 | xpBar.animateValue = xpBar.animateSetpoint; | |||
| 26632 | xpBar.animatePreviousSetpoint = xpBar.animateSetpoint; | |||
| 26633 | xpBar.animateState = ANIMATE_NONE; | |||
| 26634 | xpBar.xpLevelups = 0; | |||
| 26635 | } | |||
| 26636 | if ( hpFrame ) | |||
| 26637 | { | |||
| 26638 | HPBar.animateSetpoint = stats[player.playernum]->HP; | |||
| 26639 | HPBar.animateValue = HPBar.animateSetpoint; | |||
| 26640 | HPBar.animateValue2 = HPBar.animateSetpoint; | |||
| 26641 | HPBar.animatePreviousSetpoint = HPBar.animateSetpoint; | |||
| 26642 | HPBar.animateState = ANIMATE_NONE; | |||
| 26643 | HPBar.flashAnimState = -1; | |||
| 26644 | HPBar.flashTicks = 0; | |||
| 26645 | } | |||
| 26646 | if ( mpFrame ) | |||
| 26647 | { | |||
| 26648 | MPBar.animateSetpoint = stats[player.playernum]->MP; | |||
| 26649 | MPBar.animateValue = MPBar.animateSetpoint; | |||
| 26650 | MPBar.animateValue2 = MPBar.animateSetpoint; | |||
| 26651 | MPBar.animatePreviousSetpoint = MPBar.animateSetpoint; | |||
| 26652 | MPBar.animateState = ANIMATE_NONE; | |||
| 26653 | MPBar.flashAnimState = -1; | |||
| 26654 | MPBar.flashTicks = 0; | |||
| 26655 | } | |||
| 26656 | } | |||
| 26657 | ||||
| 26658 | ||||
| 26659 | void Player::HUD_t::updateMinimapPrompts() | |||
| 26660 | { | |||
| 26661 | if ( !mapPromptFrame ) | |||
| 26662 | { | |||
| 26663 | return; | |||
| 26664 | } | |||
| 26665 | ||||
| 26666 | bool showPrompts = false; | |||
| 26667 | if ( gamePaused ) | |||
| 26668 | { | |||
| 26669 | showPrompts = false; | |||
| 26670 | } | |||
| 26671 | else if ( ::minimapFrame && !::minimapFrame->isInvisible() ) | |||
| 26672 | { | |||
| 26673 | if ( player.hud.offsetHUDAboveHotbarHeight > 0 || !player.shootmode ) | |||
| 26674 | { | |||
| 26675 | showPrompts = false; | |||
| 26676 | } | |||
| 26677 | else | |||
| 26678 | { | |||
| 26679 | showPrompts = true; | |||
| 26680 | } | |||
| 26681 | } | |||
| 26682 | else if ( this->minimapFrame && !this->minimapFrame->isInvisible() ) | |||
| 26683 | { | |||
| 26684 | if ( player.hud.offsetHUDAboveHotbarHeight > 0 ) | |||
| 26685 | { | |||
| 26686 | showPrompts = false; | |||
| 26687 | } | |||
| 26688 | else | |||
| 26689 | { | |||
| 26690 | showPrompts = true; | |||
| 26691 | } | |||
| 26692 | } | |||
| 26693 | ||||
| 26694 | if ( !showPrompts ) | |||
| 26695 | { | |||
| 26696 | mapPromptFrame->setDisabled(true); | |||
| 26697 | return; | |||
| 26698 | } | |||
| 26699 | ||||
| 26700 | int maxHeight1 = 0; | |||
| 26701 | int maxHeight2 = 0; | |||
| 26702 | auto imgPromptFrame = mapPromptFrame->findFrame("img prompt frame"); | |||
| 26703 | auto scalePrompt = imgPromptFrame->findImage("scale prompt"); | |||
| 26704 | scalePrompt->path = Input::inputs[player.playernum].getGlyphPathForBinding("Minimap Scale"); | |||
| 26705 | scalePrompt->disabled = true; | |||
| 26706 | /*if ( auto imgGet = Image::get(scalePrompt->path.c_str()) ) | |||
| 26707 | { | |||
| 26708 | scalePrompt->pos.w = imgGet->getWidth(); | |||
| 26709 | scalePrompt->pos.h = imgGet->getHeight(); | |||
| 26710 | maxHeight1 = std::max(maxHeight1, scalePrompt->pos.h); | |||
| 26711 | scalePrompt->disabled = false; | |||
| 26712 | }*/ | |||
| 26713 | auto scaleImg = imgPromptFrame->findImage("scale img"); | |||
| 26714 | scaleImg->disabled = true; | |||
| 26715 | /*if ( !scalePrompt->disabled ) | |||
| 26716 | { | |||
| 26717 | if ( auto imgGet = Image::get(scaleImg->path.c_str()) ) | |||
| 26718 | { | |||
| 26719 | scaleImg->pos.w = imgGet->getWidth(); | |||
| 26720 | scaleImg->pos.h = imgGet->getHeight(); | |||
| 26721 | maxHeight1 = std::max(maxHeight1, scaleImg->pos.h); | |||
| 26722 | scaleImg->disabled = false; | |||
| 26723 | } | |||
| 26724 | }*/ | |||
| 26725 | auto expandPrompt = imgPromptFrame->findImage("expand prompt"); | |||
| 26726 | expandPrompt->disabled = true; | |||
| 26727 | expandPrompt->path = Input::inputs[player.playernum].getGlyphPathForBinding("Toggle Minimap"); | |||
| 26728 | if ( auto imgGet = Image::get(expandPrompt->path.c_str()) ) | |||
| 26729 | { | |||
| 26730 | expandPrompt->pos.w = imgGet->getWidth(); | |||
| 26731 | expandPrompt->pos.h = imgGet->getHeight(); | |||
| 26732 | maxHeight2 = std::max(maxHeight2, expandPrompt->pos.h); | |||
| 26733 | expandPrompt->disabled = false; | |||
| 26734 | } | |||
| 26735 | auto expandImg = imgPromptFrame->findImage("expand img"); | |||
| 26736 | expandImg->disabled = true; | |||
| 26737 | if ( !expandPrompt->disabled ) | |||
| 26738 | { | |||
| 26739 | if ( auto imgGet = Image::get(expandImg->path.c_str()) ) | |||
| 26740 | { | |||
| 26741 | expandImg->pos.w = imgGet->getWidth(); | |||
| 26742 | expandImg->pos.h = imgGet->getHeight(); | |||
| 26743 | maxHeight2 = std::max(maxHeight2, expandImg->pos.h); | |||
| 26744 | expandImg->disabled = false; | |||
| 26745 | } | |||
| 26746 | } | |||
| 26747 | std::vector<Frame::image_t*> imgs; | |||
| 26748 | if ( !expandPrompt->disabled ) | |||
| 26749 | { | |||
| 26750 | imgs.push_back(expandPrompt); | |||
| 26751 | imgs.push_back(expandImg); | |||
| 26752 | } | |||
| 26753 | if ( !scalePrompt->disabled ) | |||
| 26754 | { | |||
| 26755 | imgs.push_back(scalePrompt); | |||
| 26756 | imgs.push_back(scaleImg); | |||
| 26757 | } | |||
| 26758 | if ( imgs.empty() ) | |||
| 26759 | { | |||
| 26760 | mapPromptFrame->setDisabled(true); | |||
| 26761 | return; | |||
| 26762 | } | |||
| 26763 | ||||
| 26764 | bool alignHorizontal = !*cvar_minimap_prompt_vertical; | |||
| 26765 | int imgX = -2; | |||
| 26766 | int index = -1; | |||
| 26767 | int lowestY = 0; | |||
| 26768 | int rightX = 0; | |||
| 26769 | ||||
| 26770 | for ( auto img : imgs ) | |||
| 26771 | { | |||
| 26772 | ++index; | |||
| 26773 | if ( img->disabled ) | |||
| 26774 | { | |||
| 26775 | continue; | |||
| 26776 | } | |||
| 26777 | if ( alignHorizontal ) | |||
| 26778 | { | |||
| 26779 | imgX += 2; | |||
| 26780 | if ( index == 2 ) | |||
| 26781 | { | |||
| 26782 | imgX += 2; | |||
| 26783 | } | |||
| 26784 | img->pos.x = imgX; | |||
| 26785 | img->pos.y = (std::max(maxHeight1, maxHeight2) / 2) - img->pos.h / 2; | |||
| 26786 | if ( img->pos.y % 2 == 1 ) | |||
| 26787 | { | |||
| 26788 | ++img->pos.y; | |||
| 26789 | } | |||
| 26790 | imgX += (img->pos.w); | |||
| 26791 | lowestY = std::max(lowestY, img->pos.y + img->pos.h); | |||
| 26792 | rightX = std::max(rightX, img->pos.x + img->pos.h); | |||
| 26793 | } | |||
| 26794 | else | |||
| 26795 | { | |||
| 26796 | imgX += 2; | |||
| 26797 | if ( index == 2 ) | |||
| 26798 | { | |||
| 26799 | imgX = 0; | |||
| 26800 | } | |||
| 26801 | img->pos.x = imgX; | |||
| 26802 | if ( img == scaleImg || img == scalePrompt ) | |||
| 26803 | { | |||
| 26804 | img->pos.y = (maxHeight1 / 2) - img->pos.h / 2; | |||
| 26805 | } | |||
| 26806 | else | |||
| 26807 | { | |||
| 26808 | img->pos.y = maxHeight1 + 2 + (maxHeight2 / 2) - img->pos.h / 2; | |||
| 26809 | } | |||
| 26810 | if ( img->pos.y % 2 == 1 ) | |||
| 26811 | { | |||
| 26812 | ++img->pos.y; | |||
| 26813 | } | |||
| 26814 | imgX += (img->pos.w); | |||
| 26815 | lowestY = std::max(lowestY, img->pos.y + img->pos.h); | |||
| 26816 | rightX = std::max(rightX, img->pos.x + img->pos.h); | |||
| 26817 | } | |||
| 26818 | } | |||
| 26819 | if ( !player.minimap.bExpandPromptEnabled ) | |||
| 26820 | { | |||
| 26821 | expandPrompt->disabled = true; | |||
| 26822 | } | |||
| 26823 | if ( !player.minimap.bScalePromptEnabled ) | |||
| 26824 | { | |||
| 26825 | scalePrompt->disabled = true; | |||
| 26826 | } | |||
| 26827 | ||||
| 26828 | mapPromptFrame->setDisabled(false); | |||
| 26829 | ||||
| 26830 | auto promptBg = mapPromptFrame->findImage("prompt bg"); | |||
| 26831 | promptBg->disabled = true; | |||
| 26832 | ||||
| 26833 | SDL_Rect pos = mapPromptFrame->getSize(); | |||
| 26834 | if ( hudFrame ) | |||
| 26835 | { | |||
| 26836 | if ( alignHorizontal ) | |||
| 26837 | { | |||
| 26838 | if ( auto imgGet = Image::get(promptBg->path.c_str()) ) | |||
| 26839 | { | |||
| 26840 | if ( imgs.size() > 2 ) | |||
| 26841 | { | |||
| 26842 | promptBg->path = "*#images/ui/MapAndLog/HUD_MapPromptBase_00.png"; | |||
| 26843 | } | |||
| 26844 | else | |||
| 26845 | { | |||
| 26846 | promptBg->path = "*#images/ui/MapAndLog/HUD_MapPromptBase_Short_00.png"; | |||
| 26847 | } | |||
| 26848 | promptBg->disabled = false; | |||
| 26849 | promptBg->pos.w = imgGet->getWidth(); | |||
| 26850 | promptBg->pos.h = imgGet->getHeight(); | |||
| 26851 | pos.w = promptBg->pos.w; | |||
| 26852 | pos.h = std::max(promptBg->pos.h, lowestY); | |||
| 26853 | ||||
| 26854 | SDL_Rect imgPromptFramePos = imgPromptFrame->getSize(); | |||
| 26855 | imgPromptFramePos.w = rightX; | |||
| 26856 | imgPromptFramePos.h = lowestY; | |||
| 26857 | imgPromptFramePos.x = pos.w / 2 - imgPromptFramePos.w / 2; | |||
| 26858 | if ( imgPromptFramePos.x % 2 == 1 ) | |||
| 26859 | { | |||
| 26860 | ++imgPromptFramePos.x; | |||
| 26861 | } | |||
| 26862 | imgPromptFramePos.y = (pos.h / 2) - imgPromptFramePos.h / 2; | |||
| 26863 | if ( imgPromptFramePos.y % 2 == 1 ) | |||
| 26864 | { | |||
| 26865 | ++imgPromptFramePos.y; | |||
| 26866 | } | |||
| 26867 | imgPromptFrame->setSize(imgPromptFramePos); | |||
| 26868 | } | |||
| 26869 | pos.x = hudFrame->getSize().w - pos.w; | |||
| 26870 | if ( player.bUseCompactGUIHeight() || player.bUseCompactGUIWidth() ) | |||
| 26871 | { | |||
| 26872 | if ( imgs.size() > 2 ) | |||
| 26873 | { | |||
| 26874 | pos.x += 16; | |||
| 26875 | } | |||
| 26876 | else | |||
| 26877 | { | |||
| 26878 | pos.x += 16; | |||
| 26879 | } | |||
| 26880 | } | |||
| 26881 | pos.y = hudFrame->getSize().h - pos.h - player.hud.offsetHUDAboveHotbarHeight; | |||
| 26882 | } | |||
| 26883 | else | |||
| 26884 | { | |||
| 26885 | ||||
| 26886 | SDL_Rect imgPromptFramePos = imgPromptFrame->getSize(); | |||
| 26887 | imgPromptFramePos.x = 0; | |||
| 26888 | imgPromptFramePos.y = 0; | |||
| 26889 | imgPromptFramePos.w = rightX + 8; | |||
| 26890 | imgPromptFramePos.h = lowestY; | |||
| 26891 | imgPromptFrame->setSize(imgPromptFramePos); | |||
| 26892 | ||||
| 26893 | pos.w = imgPromptFramePos.w; | |||
| 26894 | pos.h = imgPromptFramePos.h; | |||
| 26895 | pos.x = hudFrame->getSize().w - pos.w; | |||
| 26896 | pos.y = hudFrame->getSize().h - player.minimap.minimapPos.h - pos.h; | |||
| 26897 | } | |||
| 26898 | } | |||
| 26899 | mapPromptFrame->setSize(pos); | |||
| 26900 | } | |||
| 26901 | ||||
| 26902 | static ConsoleVariable<bool> cvar_showmapseed("/showmapseed", false); | |||
| 26903 | ||||
| 26904 | void Player::HUD_t::updateGameTimer() | |||
| 26905 | { | |||
| 26906 | if ( !gameTimerFrame ) | |||
| 26907 | { | |||
| 26908 | return; | |||
| 26909 | } | |||
| 26910 | ||||
| 26911 | bool overrideGameTimerSetting = false; | |||
| 26912 | if ( splitscreen && !(player.bUseCompactGUIHeight() && player.bUseCompactGUIWidth()) | |||
| 26913 | && !player.shootmode && !FollowerMenu[player.playernum].followerMenuIsOpen() | |||
| 26914 | && !CalloutMenu[player.playernum].calloutMenuIsOpen() | |||
| 26915 | && player.gui_mode != GUI_MODE_NONE ) | |||
| 26916 | { | |||
| 26917 | if ( compactLayoutMode == COMPACT_LAYOUT_INVENTORY || player.bUseCompactGUIWidth() ) | |||
| 26918 | { | |||
| 26919 | overrideGameTimerSetting = true; | |||
| 26920 | } | |||
| 26921 | } | |||
| 26922 | ||||
| 26923 | if ( overrideGameTimerSetting ) | |||
| 26924 | { | |||
| 26925 | // display on hud in splitscreen !shootmode | |||
| 26926 | } | |||
| 26927 | else | |||
| 26928 | { | |||
| 26929 | if ( !player.shootmode || (!player.characterSheet.showGameTimerAlways || splitscreen) ) | |||
| 26930 | { | |||
| 26931 | gameTimerFrame->setDisabled(true); | |||
| 26932 | return; | |||
| 26933 | } | |||
| 26934 | } | |||
| 26935 | ||||
| 26936 | gameTimerFrame->setDisabled(false); | |||
| 26937 | SDL_Rect pos = gameTimerFrame->getSize(); | |||
| 26938 | pos.x = hudFrame->getSize().w - pos.w - 6; | |||
| 26939 | ||||
| 26940 | Field* timerText = gameTimerFrame->findField("timer txt"); | |||
| 26941 | SDL_Rect timerTextPos = timerText->getSize(); | |||
| 26942 | timerTextPos.x = 72; | |||
| 26943 | timerTextPos.y = 1; | |||
| 26944 | timerText->setSize(timerTextPos); | |||
| 26945 | ||||
| 26946 | char buf[64] = ""; | |||
| 26947 | Uint32 sec = (completionTime / TICKS_PER_SECOND50) % 60; | |||
| 26948 | Uint32 min = ((completionTime / TICKS_PER_SECOND50) / 60) % 60; | |||
| 26949 | Uint32 hour = (((completionTime / TICKS_PER_SECOND50) / 60) / 60) % 24; | |||
| 26950 | Uint32 day = ((completionTime / TICKS_PER_SECOND50) / 60) / 60 / 24; | |||
| 26951 | ||||
| 26952 | auto seed = gameTimerFrame->findField("seed txt"); | |||
| 26953 | seed->setDisabled(true); | |||
| 26954 | if ( *cvar_showmapseed ) | |||
| 26955 | { | |||
| 26956 | seed->setDisabled(false); | |||
| 26957 | pos.h = 44; | |||
| 26958 | char seedbuf[32]; | |||
| 26959 | snprintf(seedbuf, sizeof(seedbuf), "%u", mapseed); | |||
| 26960 | seed->setSize(SDL_Rect{ 0, 21, pos.w, 24 }); | |||
| 26961 | seed->setText(seedbuf); | |||
| 26962 | } | |||
| 26963 | else | |||
| 26964 | { | |||
| 26965 | pos.h = 24; | |||
| 26966 | } | |||
| 26967 | ||||
| 26968 | pos.y = gameTimerFrame->getParent()->getSize().h - pos.h; | |||
| 26969 | ||||
| 26970 | if ( player.hud.mapPromptFrame && !player.hud.mapPromptFrame->isDisabled() ) | |||
| 26971 | { | |||
| 26972 | SDL_Rect mapPromptPos = player.hud.mapPromptFrame->getSize(); | |||
| 26973 | pos.y = mapPromptPos.y + mapPromptPos.h / 2 - pos.h / 2; | |||
| 26974 | pos.x = mapPromptPos.x - pos.w - 4; | |||
| 26975 | if ( splitscreen && (player.bUseCompactGUIHeight() || player.bUseCompactGUIWidth()) ) | |||
| 26976 | { | |||
| 26977 | pos.x += 16; | |||
| 26978 | } | |||
| 26979 | } | |||
| 26980 | ||||
| 26981 | if ( day > 0 ) | |||
| 26982 | { | |||
| 26983 | snprintf(buf, sizeof(buf), "%02d:%02d:%02d:%02d", day, hour, min, sec); | |||
| 26984 | pos.x -= 24; | |||
| 26985 | } | |||
| 26986 | else | |||
| 26987 | { | |||
| 26988 | snprintf(buf, sizeof(buf), "%02d:%02d:%02d", hour, min, sec); | |||
| 26989 | } | |||
| 26990 | ||||
| 26991 | gameTimerFrame->setSize(pos); | |||
| 26992 | timerText->setText(buf); | |||
| 26993 | } | |||
| 26994 | ||||
| 26995 | void Player::HUD_t::updateXPBar() | |||
| 26996 | { | |||
| 26997 | if ( !xpFrame ) | |||
| 26998 | { | |||
| 26999 | return; | |||
| 27000 | } | |||
| 27001 | ||||
| 27002 | bool bCompactWidth = false; | |||
| 27003 | bool bCompactHeight = player.bUseCompactGUIHeight(); | |||
| 27004 | if ( player.bUseCompactGUIWidth() | |||
| 27005 | || (keystatus[SDLK_t] && enableDebugKeys) | |||
| 27006 | || (!player.bUseCompactGUIWidth() && player.bUseCompactGUIHeight() && *MainMenu::clipped_splitscreen) ) | |||
| 27007 | { | |||
| 27008 | bCompactWidth = true; | |||
| 27009 | } | |||
| 27010 | ||||
| 27011 | xpFrame->setInheritParentFrameOpacity(false); | |||
| 27012 | xpFrame->setOpacity(100.0); | |||
| 27013 | SDL_Rect pos = xpFrame->getSize(); | |||
| 27014 | pos.w = XP_FRAME_WIDTH + (bCompactWidth ? xpbarCompactOffsetWidth : xpbarOffsetWidth); | |||
| 27015 | pos.x = hudFrame->getSize().w / 2 - pos.w / 2; | |||
| 27016 | if ( bCompactWidth || bCompactHeight ) | |||
| 27017 | { | |||
| 27018 | pos.y = 0 + ((bCompactWidth || bCompactHeight) ? xpbarCompactOffsetY : xpbarOffsetY); | |||
| 27019 | } | |||
| 27020 | else | |||
| 27021 | { | |||
| 27022 | pos.y = 8 + ((bCompactWidth || bCompactHeight) ? xpbarCompactOffsetY : xpbarOffsetY); | |||
| 27023 | } | |||
| 27024 | ||||
| 27025 | bool tempHideXP = false; | |||
| 27026 | bool fadeOut = false; | |||
| 27027 | if ( !levelUpAnimation[player.playernum].lvlUps.empty() && !levelUpAnimation[player.playernum].lvlUps[0].titleFinishAnim ) | |||
| 27028 | { | |||
| 27029 | tempHideXP = true; | |||
| 27030 | } | |||
| 27031 | else if ( (player.gui_mode == GUI_MODE_FOLLOWERMENU || player.gui_mode == GUI_MODE_CALLOUT | |||
| 27032 | || player.minimap.mapWindow || player.messageZone.logWindow) | |||
| 27033 | && player.bUseCompactGUIHeight() ) | |||
| 27034 | { | |||
| 27035 | tempHideXP = true; | |||
| 27036 | } | |||
| 27037 | else if ( player.bUseCompactGUIHeight() && player.shootmode && !skillUpAnimation[player.playernum].skillUps.empty() | |||
| 27038 | && !(!levelUpAnimation[player.playernum].lvlUps.empty() && levelUpAnimation[player.playernum].lvlUps[0].titleFinishAnim) ) | |||
| 27039 | { | |||
| 27040 | // hide xp in compact height, if skillup active and level up isn't playing | |||
| 27041 | tempHideXP = true; | |||
| 27042 | fadeOut = true; | |||
| 27043 | } | |||
| 27044 | if ( tempHideXP ) | |||
| 27045 | { | |||
| 27046 | if ( fadeOut ) | |||
| 27047 | { | |||
| 27048 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 27049 | real_t setpointDiff = fpsScale * std::max(.1, (1.0 - animHideXP)) / 2.5; | |||
| 27050 | animHideXP += setpointDiff; | |||
| 27051 | animHideXP = std::min(1.0, animHideXP); | |||
| 27052 | } | |||
| 27053 | else | |||
| 27054 | { | |||
| 27055 | animHideXP = 1.0; | |||
| 27056 | } | |||
| 27057 | } | |||
| 27058 | else | |||
| 27059 | { | |||
| 27060 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 27061 | real_t setpointDiff = fpsScale * std::max(.1, (animHideXP)) / 2.5; | |||
| 27062 | animHideXP -= setpointDiff; | |||
| 27063 | animHideXP = std::max(0.0, animHideXP); | |||
| 27064 | } | |||
| 27065 | //pos.y -= animHideXP * (pos.y + pos.h); | |||
| 27066 | xpFrame->setOpacity((1.0 - animHideXP) * 100.0); | |||
| 27067 | xpFrame->setSize(pos); | |||
| 27068 | ||||
| 27069 | auto xpBg = xpFrame->findImage("xp img base"); | |||
| 27070 | auto xpProgress = xpFrame->findImage("xp img progress"); | |||
| 27071 | xpProgress->disabled = true; | |||
| 27072 | auto xpProgressEndCap = xpFrame->findImage("xp img progress endcap"); | |||
| 27073 | auto endCapRight = xpFrame->findImage("xp img endcap right"); | |||
| 27074 | xpBg->pos.w = pos.w; | |||
| 27075 | if ( auto xpBgFlair = xpFrame->findImage("xp img base flair") ) | |||
| 27076 | { | |||
| 27077 | xpBgFlair->pos.w = pos.w - 8; | |||
| 27078 | } | |||
| 27079 | endCapRight->pos.x = pos.w - endCapRight->pos.w; | |||
| 27080 | ||||
| 27081 | xpBar.animateSetpoint = std::min(100, stats[player.playernum]->EXP); | |||
| 27082 | xpBar.maxValue = 1000.0; | |||
| 27083 | ||||
| 27084 | if ( xpBar.animateState == ANIMATE_LEVELUP_RISING ) | |||
| 27085 | { | |||
| 27086 | xpBar.animateTicks = ticks; | |||
| 27087 | ||||
| 27088 | real_t fpsScale = getFPSScale(144.0); | |||
| 27089 | xpBar.animateValue += fpsScale * (10); // constant speed | |||
| 27090 | xpBar.animateValue = std::min(xpBar.maxValue, xpBar.animateValue); | |||
| 27091 | if ( xpBar.animateValue == xpBar.maxValue ) | |||
| 27092 | { | |||
| 27093 | xpBar.animateState = ANIMATE_LEVELUP_FALLING; | |||
| 27094 | } | |||
| 27095 | } | |||
| 27096 | else if ( xpBar.animateState == ANIMATE_LEVELUP_FALLING ) | |||
| 27097 | { | |||
| 27098 | if ( ticks - xpBar.animateTicks > TICKS_PER_SECOND50 * 2 ) | |||
| 27099 | { | |||
| 27100 | int decrement = 40; | |||
| 27101 | double scaledDecrement = (decrement * (getFPSScale(144.0))); | |||
| 27102 | xpBar.animateValue -= scaledDecrement; | |||
| 27103 | if ( xpBar.animateValue <= 0 ) | |||
| 27104 | { | |||
| 27105 | xpBar.animateValue = 0.0; | |||
| 27106 | xpBar.xpLevelups = 0; // disable looping maybe one day use it | |||
| 27107 | if ( xpBar.xpLevelups > 1 ) | |||
| 27108 | { | |||
| 27109 | --xpBar.xpLevelups; | |||
| 27110 | xpBar.animateState = ANIMATE_LEVELUP_RISING; | |||
| 27111 | } | |||
| 27112 | else | |||
| 27113 | { | |||
| 27114 | xpBar.xpLevelups = 0; | |||
| 27115 | xpBar.animateState = ANIMATE_NONE; | |||
| 27116 | } | |||
| 27117 | } | |||
| 27118 | } | |||
| 27119 | } | |||
| 27120 | else | |||
| 27121 | { | |||
| 27122 | int increment = 3; | |||
| 27123 | double scaledIncrement = (increment * (getFPSScale(144.0))); | |||
| 27124 | if ( xpBar.animateValue < xpBar.animateSetpoint * 10 ) | |||
| 27125 | { | |||
| 27126 | //real_t diff = std::max(.1, (xpBar.animateSetpoint * 10 - xpBar.animateValue) / 200.0); // 0.1-5 value | |||
| 27127 | //if ( xpBar.animateSetpoint * 10 >= xpBar.maxValue ) | |||
| 27128 | //{ | |||
| 27129 | // diff = 5; | |||
| 27130 | //} | |||
| 27131 | //scaledIncrement *= 0.2 * pow(diff, 2) + .5; | |||
| 27132 | //xpBar.animateValue = std::min(xpBar.animateSetpoint * 10.0, xpBar.animateValue + scaledIncrement); | |||
| 27133 | ||||
| 27134 | real_t setpointDiff = std::max(10.0, xpBar.animateSetpoint * 10.0 - xpBar.animateValue); | |||
| 27135 | real_t fpsScale = getFPSScale(144.0); | |||
| 27136 | xpBar.animateValue += fpsScale * (setpointDiff / 100.0); // reach it in x intervals, scaled to FPS | |||
| 27137 | xpBar.animateValue = std::min(static_cast<real_t>(xpBar.animateSetpoint * 10.0), xpBar.animateValue); | |||
| 27138 | //messagePlayer(0, "%.2f | %.2f", diff, scaledIncrement); | |||
| 27139 | } | |||
| 27140 | else if ( xpBar.animateValue > xpBar.animateSetpoint * 10 ) | |||
| 27141 | { | |||
| 27142 | xpBar.animateValue = xpBar.animateSetpoint * 10; // invalid state, reset progress bar | |||
| 27143 | } | |||
| 27144 | //else if ( xpBar.animateValue > xpBar.animateSetpoint * 10 ) | |||
| 27145 | //{ | |||
| 27146 | // real_t fpsScale = getFPSScale(144.0); | |||
| 27147 | // xpBar.animateValue += fpsScale * (10); // constant speed | |||
| 27148 | // xpBar.animateValue = std::min(xpBar.maxValue, xpBar.animateValue); | |||
| 27149 | //} | |||
| 27150 | //else | |||
| 27151 | //{ | |||
| 27152 | // xpBar.animateTicks = ticks; | |||
| 27153 | //} | |||
| 27154 | ||||
| 27155 | xpBar.animateTicks = ticks; | |||
| 27156 | ||||
| 27157 | //if ( xpBar.animateValue == xpBar.maxValue ) | |||
| 27158 | //{ | |||
| 27159 | // xpBar.animateState = ANIMATE_LEVELUP; | |||
| 27160 | //} | |||
| 27161 | } | |||
| 27162 | ||||
| 27163 | //if ( xpInfo.cycleProcessedOnTick != ticks ) | |||
| 27164 | //{ | |||
| 27165 | // ++xpInfo.cycleTicks; | |||
| 27166 | //} | |||
| 27167 | ||||
| 27168 | //if ( bCompactWidth ) | |||
| 27169 | //{ | |||
| 27170 | // if ( xpInfo.cycleStatus == XPInfo_t::CYCLE_NONE ) | |||
| 27171 | // { | |||
| 27172 | // xpInfo.cycleStatus = XPInfo_t::CYCLE_LVL; | |||
| 27173 | // } | |||
| 27174 | ||||
| 27175 | // if ( !xpInfo.fadeIn ) | |||
| 27176 | // { | |||
| 27177 | // xpInfo.cycleTicks = 0; | |||
| 27178 | // } | |||
| 27179 | ||||
| 27180 | // if ( xpInfo.cycleTicks > 0 && | |||
| 27181 | // (xpInfo.cycleTicks >= TICKS_PER_SECOND * 5 || xpBar.animateState != ANIMATE_NONE) ) | |||
| 27182 | // { | |||
| 27183 | // xpInfo.fadeIn = false; | |||
| 27184 | // } | |||
| 27185 | ||||
| 27186 | // if ( !xpInfo.fadeIn ) | |||
| 27187 | // { | |||
| 27188 | // const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 27189 | // real_t setpointDiffX = fpsScale * std::max(.1, (xpInfo.fade)) / (2.5); | |||
| 27190 | // xpInfo.fade -= setpointDiffX; | |||
| 27191 | // xpInfo.fade = std::max(0.0, xpInfo.fade); | |||
| 27192 | // if ( xpInfo.fade <= 0.0 ) | |||
| 27193 | // { | |||
| 27194 | // if ( xpInfo.cycleStatus == XPInfo_t::CYCLE_LVL ) | |||
| 27195 | // { | |||
| 27196 | // xpInfo.cycleStatus = XPInfo_t::CYCLE_XP; | |||
| 27197 | // } | |||
| 27198 | // else | |||
| 27199 | // { | |||
| 27200 | // xpInfo.cycleStatus = XPInfo_t::CYCLE_LVL; | |||
| 27201 | // } | |||
| 27202 | // xpInfo.fadeIn = true; | |||
| 27203 | // } | |||
| 27204 | // } | |||
| 27205 | // else | |||
| 27206 | // { | |||
| 27207 | // const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 27208 | // real_t setpointDiffX = fpsScale * std::max(.1, (1.0 - xpInfo.fade)) / (2.5); | |||
| 27209 | // xpInfo.fade += setpointDiffX; | |||
| 27210 | // xpInfo.fade = std::min(1.0, xpInfo.fade); | |||
| 27211 | // } | |||
| 27212 | ||||
| 27213 | // messagePlayer(0, MESSAGE_DEBUG, "%f", xpInfo.fade); | |||
| 27214 | //} | |||
| 27215 | //else | |||
| 27216 | { | |||
| 27217 | xpInfo.cycleStatus = XPInfo_t::CYCLE_NONE; | |||
| 27218 | xpInfo.cycleTicks = 0; | |||
| 27219 | xpInfo.fade = 1.0; | |||
| 27220 | } | |||
| 27221 | ||||
| 27222 | { | |||
| 27223 | char playerXPText[16]; | |||
| 27224 | ||||
| 27225 | auto xpTextStatic = xpFrame->findField("xp text static"); | |||
| 27226 | SDL_Rect xpTextStaticPos = xpTextStatic->getSize(); | |||
| 27227 | ||||
| 27228 | int offsetx = pos.w / 2 - xpTextStaticPos.w - 24; | |||
| 27229 | if ( bCompactWidth ) | |||
| 27230 | { | |||
| 27231 | xpTextStatic->setDisabled(true); | |||
| 27232 | snprintf(playerXPText, sizeof(playerXPText), "%.f %s", xpBar.animateValue / 10, Language::get(6107)); | |||
| 27233 | } | |||
| 27234 | else | |||
| 27235 | { | |||
| 27236 | snprintf(playerXPText, sizeof(playerXPText), "%.f", xpBar.animateValue / 10); | |||
| 27237 | xpTextStatic->setDisabled(false); | |||
| 27238 | } | |||
| 27239 | ||||
| 27240 | xpTextStaticPos.x = pos.w / 2 - 4 + offsetx; | |||
| 27241 | xpTextStatic->setSize(xpTextStaticPos); | |||
| 27242 | auto xpText = xpFrame->findField("xp text current"); | |||
| 27243 | xpText->setText(playerXPText); | |||
| 27244 | SDL_Rect xpTextPos = xpText->getSize(); | |||
| 27245 | if ( bCompactWidth ) | |||
| 27246 | { | |||
| 27247 | xpTextPos.x = pos.w - 32 - xpTextPos.w; | |||
| 27248 | } | |||
| 27249 | else | |||
| 27250 | { | |||
| 27251 | xpTextPos.x = pos.w / 2 - (4 * 2) - xpTextPos.w + offsetx; | |||
| 27252 | } | |||
| 27253 | xpText->setSize(xpTextPos); | |||
| 27254 | ||||
| 27255 | if ( xpInfo.cycleStatus != XPInfo_t::CYCLE_NONE ) | |||
| 27256 | { | |||
| 27257 | Uint8 r, g, b, a; | |||
| 27258 | getColor(xpText->getColor(), &r, &g, &b, &a); | |||
| 27259 | if ( xpInfo.cycleStatus == XPInfo_t::CYCLE_XP ) | |||
| 27260 | { | |||
| 27261 | a = 255 * xpInfo.fade; | |||
| 27262 | } | |||
| 27263 | else | |||
| 27264 | { | |||
| 27265 | a = 0; | |||
| 27266 | } | |||
| 27267 | xpText->setColor(makeColor(r, g, b, a)); | |||
| 27268 | xpTextStatic->setColor(makeColor(r, g, b, a)); | |||
| 27269 | } | |||
| 27270 | } | |||
| 27271 | ||||
| 27272 | { | |||
| 27273 | auto textLevel = xpFrame->findField("xp text lvl"); | |||
| 27274 | textLevel->setDisabled(false); | |||
| 27275 | char textLevelBuf[64]; | |||
| 27276 | snprintf(textLevelBuf, sizeof(textLevelBuf), "LVL %d", stats[player.playernum]->LVL); | |||
| 27277 | textLevel->setText(textLevelBuf); | |||
| 27278 | SDL_Rect textPos = textLevel->getSize(); | |||
| 27279 | ||||
| 27280 | if ( auto textGet = textLevel->getTextObject() ) | |||
| 27281 | { | |||
| 27282 | textPos.w = textGet->getWidth(); | |||
| 27283 | } | |||
| 27284 | textPos.x = 32; | |||
| 27285 | textLevel->setSize(textPos); | |||
| 27286 | ||||
| 27287 | { | |||
| 27288 | if ( xpInfo.cycleStatus != XPInfo_t::CYCLE_NONE ) | |||
| 27289 | { | |||
| 27290 | Uint8 r, g, b, a; | |||
| 27291 | getColor(textLevel->getColor(), &r, &g, &b, &a); | |||
| 27292 | if ( xpInfo.cycleStatus == XPInfo_t::CYCLE_LVL ) | |||
| 27293 | { | |||
| 27294 | a = 255 * xpInfo.fade; | |||
| 27295 | } | |||
| 27296 | else | |||
| 27297 | { | |||
| 27298 | a = 0; | |||
| 27299 | } | |||
| 27300 | textLevel->setColor(makeColor(r, g, b, a)); | |||
| 27301 | } | |||
| 27302 | } | |||
| 27303 | ||||
| 27304 | auto textClass = xpFrame->findField("xp text class"); | |||
| 27305 | textClass->setDisabled(true); | |||
| 27306 | if ( !bCompactWidth ) | |||
| 27307 | { | |||
| 27308 | std::string classname = playerClassLangEntry(client_classes[player.playernum], player.playernum); | |||
| 27309 | if ( !classname.empty() ) | |||
| 27310 | { | |||
| 27311 | capitalizeString(classname); | |||
| 27312 | textClass->setText(classname.c_str()); | |||
| 27313 | textClass->setDisabled(false); | |||
| 27314 | } | |||
| 27315 | if ( true ) | |||
| 27316 | { | |||
| 27317 | textClass->setColor(0xFFFFFFFF); | |||
| 27318 | } | |||
| 27319 | else if ( client_classes[player.playernum] >= CLASS_CONJURER && client_classes[player.playernum] <= CLASS_BREWER ) | |||
| 27320 | { | |||
| 27321 | textClass->setColor(hudColors.characterDLC1ClassText); | |||
| 27322 | } | |||
| 27323 | else if ( client_classes[player.playernum] >= CLASS_MACHINIST && client_classes[player.playernum] <= CLASS_HUNTER ) | |||
| 27324 | { | |||
| 27325 | textClass->setColor(hudColors.characterDLC2ClassText); | |||
| 27326 | } | |||
| 27327 | else | |||
| 27328 | { | |||
| 27329 | textClass->setColor(hudColors.characterBaseClassText); | |||
| 27330 | } | |||
| 27331 | { | |||
| 27332 | SDL_Rect textPos2 = textClass->getSize(); | |||
| 27333 | if ( auto textGet = textClass->getTextObject() ) | |||
| 27334 | { | |||
| 27335 | textPos2.w = textGet->getWidth(); | |||
| 27336 | } | |||
| 27337 | textPos2.x = textPos.x + textPos.w + 8; | |||
| 27338 | textClass->setSize(textPos2); | |||
| 27339 | ||||
| 27340 | if ( xpInfo.cycleStatus != XPInfo_t::CYCLE_NONE ) | |||
| 27341 | { | |||
| 27342 | Uint8 r, g, b, a; | |||
| 27343 | getColor(textClass->getColor(), &r, &g, &b, &a); | |||
| 27344 | if ( xpInfo.cycleStatus == XPInfo_t::CYCLE_LVL ) | |||
| 27345 | { | |||
| 27346 | a = 255 * xpInfo.fade; | |||
| 27347 | } | |||
| 27348 | else | |||
| 27349 | { | |||
| 27350 | a = 0; | |||
| 27351 | } | |||
| 27352 | textClass->setColor(makeColor(r, g, b, a)); | |||
| 27353 | } | |||
| 27354 | } | |||
| 27355 | } | |||
| 27356 | } | |||
| 27357 | ||||
| 27358 | ||||
| 27359 | real_t percent = xpBar.animateValue / 1000.0; | |||
| 27360 | xpProgress->pos.w = std::max(1, static_cast<int>((xpBg->pos.w - xpProgressEndCap->pos.w) * percent)); | |||
| 27361 | if ( !xpProgress->disabled ) | |||
| 27362 | { | |||
| 27363 | xpProgressEndCap->pos.x = xpProgress->pos.x + xpProgress->pos.w; | |||
| 27364 | } | |||
| 27365 | ||||
| 27366 | auto xpProgressClipFrame = xpFrame->findFrame("xp progress clipping frame"); | |||
| 27367 | SDL_Rect clipFramePos = xpProgressClipFrame->getSize(); | |||
| 27368 | clipFramePos.w = std::max(1, static_cast<int>((xpBg->pos.w ) * percent)); | |||
| 27369 | if ( xpProgress->disabled ) | |||
| 27370 | { | |||
| 27371 | xpProgressEndCap->pos.x = clipFramePos.x + clipFramePos.w; | |||
| 27372 | ||||
| 27373 | bool animate = true; | |||
| 27374 | if ( ticks % 5 == 0 ) | |||
| 27375 | { | |||
| 27376 | bool moving = (xpBar.animateSetpoint * 10.0 - xpBar.animateValue != 0); | |||
| 27377 | std::string playerStr = "00"; | |||
| 27378 | switch ( player.playernum ) | |||
| 27379 | { | |||
| 27380 | case 0: | |||
| 27381 | default: | |||
| 27382 | break; | |||
| 27383 | case 1: | |||
| 27384 | playerStr = "01"; | |||
| 27385 | break; | |||
| 27386 | case 2: | |||
| 27387 | playerStr = "02"; | |||
| 27388 | break; | |||
| 27389 | case 3: | |||
| 27390 | playerStr = "03"; | |||
| 27391 | break; | |||
| 27392 | } | |||
| 27393 | int xpPathNum = player.playernum; | |||
| 27394 | if ( player.playernum >= playerXPCapPaths.size() ) | |||
| 27395 | { | |||
| 27396 | xpPathNum = 0; | |||
| 27397 | } | |||
| 27398 | if ( moving && xpProgressEndCap->path == playerXPCapPaths[xpPathNum][0] ) | |||
| 27399 | { | |||
| 27400 | xpProgressEndCap->path = playerXPCapPaths[xpPathNum][1]; | |||
| 27401 | } | |||
| 27402 | else if ( xpProgressEndCap->path == playerXPCapPaths[xpPathNum][1] ) | |||
| 27403 | { | |||
| 27404 | xpProgressEndCap->path = playerXPCapPaths[xpPathNum][2]; | |||
| 27405 | } | |||
| 27406 | else if ( xpProgressEndCap->path == playerXPCapPaths[xpPathNum][2] ) | |||
| 27407 | { | |||
| 27408 | xpProgressEndCap->path = playerXPCapPaths[xpPathNum][3]; | |||
| 27409 | } | |||
| 27410 | else if ( xpProgressEndCap->path == playerXPCapPaths[xpPathNum][3] ) | |||
| 27411 | { | |||
| 27412 | xpProgressEndCap->path = playerXPCapPaths[xpPathNum][4]; | |||
| 27413 | } | |||
| 27414 | else if ( xpProgressEndCap->path == playerXPCapPaths[player.playernum][4] ) | |||
| 27415 | { | |||
| 27416 | xpProgressEndCap->path = playerXPCapPaths[xpPathNum][0]; | |||
| 27417 | } | |||
| 27418 | } | |||
| 27419 | } | |||
| 27420 | xpProgressClipFrame->setSize(clipFramePos); | |||
| 27421 | auto xpProgressClipFrameImg = xpProgressClipFrame->findImage("xp img progress clipped"); | |||
| 27422 | xpProgressClipFrameImg->pos.x = -(xpProgressClipFrameImg->pos.w - pos.w) / 2; | |||
| 27423 | } | |||
| 27424 | ||||
| 27425 | bool EnemyHPDamageBarHandler::bEnemyBarSimpleBlit = false; | |||
| 27426 | static ConsoleVariable<bool> cvar_enemybar_simple_blit("/enemybar_simple_blit", true); | |||
| 27427 | ||||
| 27428 | // to nest deep maps and suppress visual studio warnings | |||
| 27429 | struct enemybarMapLowDurationTick_k { | |||
| 27430 | std::map<bool, SDL_Surface*> m; | |||
| 27431 | ~enemybarMapLowDurationTick_k() | |||
| 27432 | { | |||
| 27433 | if ( EnemyHPDamageBarHandler::bEnemyBarSimpleBlit ) | |||
| 27434 | { | |||
| 27435 | for ( auto& entry : m ) | |||
| 27436 | { | |||
| 27437 | if ( entry.second ) | |||
| 27438 | { | |||
| 27439 | SDL_FreeSurface(entry.second); | |||
| 27440 | entry.second = nullptr; | |||
| 27441 | } | |||
| 27442 | } | |||
| 27443 | } | |||
| 27444 | }; | |||
| 27445 | }; | |||
| 27446 | struct enemybarEffectMapFx2_lowDuration_k { | |||
| 27447 | std::map<Uint32, enemybarMapLowDurationTick_k> m; | |||
| 27448 | }; | |||
| 27449 | struct enemybarEffectMapFx1_lowDuration_k { | |||
| 27450 | std::map<Uint32, enemybarEffectMapFx2_lowDuration_k> m; | |||
| 27451 | }; | |||
| 27452 | struct enemybarEffectMapFx2_k { | |||
| 27453 | std::map<Uint32, enemybarEffectMapFx1_lowDuration_k> m; | |||
| 27454 | }; | |||
| 27455 | struct enemybarEffectMapFx1_k { | |||
| 27456 | std::map<Uint32, enemybarEffectMapFx2_k> m; | |||
| 27457 | }; | |||
| 27458 | enemybarEffectMapFx1_k enemyBarEffectMap; | |||
| 27459 | SDL_Surface* enemyBarEffectMapExists(Uint32 fx1, Uint32 fx2, Uint32 fx_lowDuration1, Uint32 fx_lowDuration2, bool lowDurationTicks) | |||
| 27460 | { | |||
| 27461 | if ( enemyBarEffectMap.m.find(fx1) != enemyBarEffectMap.m.end() ) | |||
| 27462 | { | |||
| 27463 | auto& m1 = enemyBarEffectMap.m[fx1]; | |||
| 27464 | if ( m1.m.find(fx2) != m1.m.end() ) | |||
| 27465 | { | |||
| 27466 | auto& m2 = m1.m[fx2]; | |||
| 27467 | if ( m2.m.find(fx_lowDuration1) != m2.m.end() ) | |||
| 27468 | { | |||
| 27469 | auto& m3 = m2.m[fx_lowDuration1]; | |||
| 27470 | if ( m3.m.find(fx_lowDuration2) != m3.m.end() ) | |||
| 27471 | { | |||
| 27472 | auto& m4 = m3.m[fx_lowDuration2]; | |||
| 27473 | if ( m4.m.find(lowDurationTicks) != m4.m.end() ) | |||
| 27474 | { | |||
| 27475 | return m4.m[lowDurationTicks]; | |||
| 27476 | } | |||
| 27477 | } | |||
| 27478 | } | |||
| 27479 | } | |||
| 27480 | } | |||
| 27481 | return nullptr; | |||
| 27482 | } | |||
| 27483 | void enemyBarEffectMapInsert(Uint32 fx1, Uint32 fx2, Uint32 fx_lowDuration1, Uint32 fx_lowDuration2, bool lowDurationTicks, | |||
| 27484 | SDL_Surface* surf) | |||
| 27485 | { | |||
| 27486 | enemyBarEffectMap.m[fx1].m[fx2].m[fx_lowDuration1].m[fx_lowDuration2].m[lowDurationTicks] = surf; | |||
| 27487 | } | |||
| 27488 | ||||
| 27489 | // to nest deep maps and suppress visual studio warnings | |||
| 27490 | struct enemybarMapFx2_lowDuration_k { | |||
| 27491 | std::map<Uint32, SDL_Surface*> m; | |||
| 27492 | ~enemybarMapFx2_lowDuration_k() | |||
| 27493 | { | |||
| 27494 | if ( EnemyHPDamageBarHandler::bEnemyBarSimpleBlit ) | |||
| 27495 | { | |||
| 27496 | for ( auto& entry : m ) | |||
| 27497 | { | |||
| 27498 | if ( entry.second ) | |||
| 27499 | { | |||
| 27500 | SDL_FreeSurface(entry.second); | |||
| 27501 | entry.second = nullptr; | |||
| 27502 | } | |||
| 27503 | } | |||
| 27504 | } | |||
| 27505 | }; | |||
| 27506 | }; | |||
| 27507 | struct enemybarMapFx1_lowDuration_k { | |||
| 27508 | std::map<Uint32, enemybarMapFx2_lowDuration_k> m; | |||
| 27509 | }; | |||
| 27510 | struct enemybarMapFx2_k { | |||
| 27511 | std::map<Uint32, enemybarMapFx1_lowDuration_k> m; | |||
| 27512 | }; | |||
| 27513 | struct enemybarMapFx1_k { | |||
| 27514 | std::map<Uint32, enemybarMapFx2_k> m; | |||
| 27515 | }; | |||
| 27516 | struct enemybarMapProgress_k { | |||
| 27517 | std::map<Uint32, enemybarMapFx1_k> m; | |||
| 27518 | }; | |||
| 27519 | struct enemybarMapTotalSize_k { | |||
| 27520 | std::map<Uint32, enemybarMapProgress_k> m; | |||
| 27521 | }; | |||
| 27522 | struct enemybarMapName_k { | |||
| 27523 | std::map<std::string, enemybarMapTotalSize_k> m; | |||
| 27524 | }; | |||
| 27525 | enemybarMapName_k enemyBarMap; | |||
| 27526 | SDL_Surface* enemyBarMapExists(std::string name, int baseWidth, int baseHeight, | |||
| 27527 | int progressWidth, int damageWidth, | |||
| 27528 | Uint32 fx1, Uint32 fx2, Uint32 fx_lowDuration1, Uint32 fx_lowDuration2) | |||
| 27529 | { | |||
| 27530 | if ( enemyBarMap.m.find(name) != enemyBarMap.m.end() ) | |||
| 27531 | { | |||
| 27532 | auto& m1 = enemyBarMap.m[name]; | |||
| 27533 | Uint32 totalSizeKey = baseWidth & 0xFFFF; | |||
| 27534 | totalSizeKey |= (baseHeight << 16) & 0xFF0000; | |||
| 27535 | totalSizeKey |= (((ticks % 25) >= 12) << 24) & 0xFF000000; | |||
| 27536 | if ( m1.m.find(totalSizeKey) != m1.m.end() ) | |||
| 27537 | { | |||
| 27538 | auto& m2 = m1.m[totalSizeKey]; | |||
| 27539 | Uint32 progressDamageKey = progressWidth & 0xFFFF; | |||
| 27540 | progressDamageKey |= (damageWidth << 16) & 0xFFFF0000; | |||
| 27541 | if ( m2.m.find(progressDamageKey) != m2.m.end() ) | |||
| 27542 | { | |||
| 27543 | auto& m3 = m2.m[progressDamageKey]; | |||
| 27544 | if ( m3.m.find(fx1) != m3.m.end() ) | |||
| 27545 | { | |||
| 27546 | auto& m4 = m3.m[fx1]; | |||
| 27547 | if ( m4.m.find(fx2) != m4.m.end() ) | |||
| 27548 | { | |||
| 27549 | auto& m5 = m4.m[fx2]; | |||
| 27550 | if ( m5.m.find(fx_lowDuration1) != m5.m.end() ) | |||
| 27551 | { | |||
| 27552 | auto& m6 = m5.m[fx_lowDuration1]; | |||
| 27553 | if ( m6.m.find(fx_lowDuration2) != m6.m.end() ) | |||
| 27554 | { | |||
| 27555 | return m6.m[fx_lowDuration2]; | |||
| 27556 | } | |||
| 27557 | } | |||
| 27558 | } | |||
| 27559 | } | |||
| 27560 | } | |||
| 27561 | } | |||
| 27562 | } | |||
| 27563 | return nullptr; | |||
| 27564 | } | |||
| 27565 | static void enemyBarMapInsert(std::string name, int baseWidth, int baseHeight, int progressWidth, int damageWidth, | |||
| 27566 | Uint32 statusfx1, Uint32 statusfx2, | |||
| 27567 | Uint32 statusfx_lowDuration1, Uint32 statusfx_lowDuration2, | |||
| 27568 | SDL_Surface* surf) | |||
| 27569 | { | |||
| 27570 | Uint32 totalSizeKey = baseWidth & 0xFFFF; | |||
| 27571 | totalSizeKey |= (baseHeight << 16) & 0xFF0000; | |||
| 27572 | totalSizeKey |= (((ticks % 25) >= 12) << 24) & 0xFF000000; | |||
| 27573 | Uint32 progressDamageKey = progressWidth & 0xFFFF; | |||
| 27574 | progressDamageKey |= ((damageWidth & 0xFFFF) << 16); | |||
| 27575 | enemyBarMap.m[name].m[totalSizeKey].m[progressDamageKey].m[statusfx1].m[statusfx2].m[statusfx_lowDuration1].m[statusfx_lowDuration2] = surf; | |||
| 27576 | } | |||
| 27577 | ||||
| 27578 | SDL_Surface* EnemyHPDamageBarHandler::EnemyHPDetails::blitEnemyBar(const int player, SDL_Surface* statusEffectSprite) | |||
| 27579 | { | |||
| 27580 | Frame* frame = players[player]->hud.enemyBarFrame; | |||
| 27581 | if ( !frame || !players[player]->isLocalPlayer() ) | |||
| 27582 | { | |||
| 27583 | return nullptr; | |||
| 27584 | } | |||
| 27585 | ||||
| 27586 | auto baseBg = frame->findImage("base img"); | |||
| 27587 | auto baseEndCap = frame->findImage("base img endcap"); | |||
| 27588 | real_t frameOpacity = frame->getOpacity() / 100.0; | |||
| 27589 | frameOpacity = 1.0; | |||
| 27590 | /*if ( EnemyHPDamageBarHandler::bEnemyBarSimpleBlit ) | |||
| 27591 | { | |||
| 27592 | frameOpacity = 1.0; | |||
| 27593 | }*/ | |||
| 27594 | ||||
| 27595 | auto foregroundFrame = frame->findFrame("bar progress frame"); | |||
| 27596 | auto hpProgress = foregroundFrame->findImage("progress img"); | |||
| 27597 | auto hpProgressEndcap = foregroundFrame->findImage("progress img endcap"); | |||
| 27598 | ||||
| 27599 | auto dmgFrame = frame->findFrame("bar dmg frame"); | |||
| 27600 | auto dmgProgress = dmgFrame->findImage("dmg img"); | |||
| 27601 | auto dmgEndCap = dmgFrame->findImage("dmg img endcap"); | |||
| 27602 | ||||
| 27603 | auto nameField = frame->findField("enemy name txt"); | |||
| 27604 | ||||
| 27605 | auto skullFrame = frame->findFrame("skull frame"); | |||
| 27606 | int totalWidth = baseBg->pos.x + baseBg->pos.w + baseEndCap->pos.w; | |||
| 27607 | int totalHeight = frame->getSize().h; | |||
| 27608 | int statusEffectOffsetY = 0; | |||
| 27609 | ||||
| 27610 | if ( statusEffectSprite ) | |||
| 27611 | { | |||
| 27612 | statusEffectOffsetY = statusEffectSprite->h; | |||
| 27613 | totalHeight += statusEffectOffsetY; | |||
| 27614 | } | |||
| 27615 | ||||
| 27616 | SDL_Surface* hashSurf = nullptr; | |||
| 27617 | if ( EnemyHPDamageBarHandler::bEnemyBarSimpleBlit ) | |||
| 27618 | { | |||
| 27619 | hashSurf = enemyBarMapExists(nameField->getText(), | |||
| 27620 | totalWidth, totalHeight, | |||
| 27621 | dmgProgress->pos.w, hpProgress->pos.w, | |||
| 27622 | enemy_statusEffects1, | |||
| 27623 | enemy_statusEffects2, | |||
| 27624 | enemy_statusEffectsLowDuration1, | |||
| 27625 | enemy_statusEffectsLowDuration2); | |||
| 27626 | if ( !hashSurf ) | |||
| 27627 | { | |||
| 27628 | //messagePlayer(0, MESSAGE_DEBUG, "Hash for enemy bar not found!"); | |||
| 27629 | } | |||
| 27630 | else | |||
| 27631 | { | |||
| 27632 | return hashSurf; | |||
| 27633 | } | |||
| 27634 | } | |||
| 27635 | ||||
| 27636 | SDL_Surface* sprite = SDL_CreateRGBSurface(0, totalWidth, totalHeight, 32, | |||
| 27637 | 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); | |||
| 27638 | for ( auto& img : frame->getImages() ) | |||
| 27639 | { | |||
| 27640 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get(img->path.c_str())->getSurf()); | |||
| 27641 | Uint8 r, g, b, a; | |||
| 27642 | getColor(img->color, &r, &g, &b, &a); | |||
| 27643 | SDL_SetSurfaceAlphaMod(srcSurf, a * frameOpacity); | |||
| 27644 | SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 27645 | SDL_Rect pos = img->pos; | |||
| 27646 | pos.y += statusEffectOffsetY; | |||
| 27647 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, sprite, &pos); | |||
| 27648 | } | |||
| 27649 | for ( auto& img : dmgFrame->getImages() ) | |||
| 27650 | { | |||
| 27651 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get(img->path.c_str())->getSurf()); | |||
| 27652 | Uint8 r, g, b, a; | |||
| 27653 | getColor(img->color, &r, &g, &b, &a); | |||
| 27654 | if ( EnemyHPDamageBarHandler::bEnemyBarSimpleBlit && a < 255 ) { continue; } | |||
| 27655 | SDL_SetSurfaceAlphaMod(srcSurf, a * frameOpacity); | |||
| 27656 | //SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 27657 | SDL_Rect pos = img->pos; | |||
| 27658 | pos.x += dmgFrame->getSize().x; | |||
| 27659 | pos.y += dmgFrame->getSize().y; | |||
| 27660 | pos.y += statusEffectOffsetY; | |||
| 27661 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, sprite, &pos); | |||
| 27662 | } | |||
| 27663 | for ( auto& img : foregroundFrame->getImages() ) | |||
| 27664 | { | |||
| 27665 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get(img->path.c_str())->getSurf()); | |||
| 27666 | Uint8 r, g, b, a; | |||
| 27667 | getColor(img->color, &r, &g, &b, &a); | |||
| 27668 | SDL_SetSurfaceAlphaMod(srcSurf, a * frameOpacity); | |||
| 27669 | //SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 27670 | SDL_Rect pos = img->pos; | |||
| 27671 | pos.x += foregroundFrame->getSize().x; | |||
| 27672 | pos.y += foregroundFrame->getSize().y; | |||
| 27673 | pos.y += statusEffectOffsetY; | |||
| 27674 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, sprite, &pos); | |||
| 27675 | } | |||
| 27676 | for ( auto& img : skullFrame->getImages() ) | |||
| 27677 | { | |||
| 27678 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get(img->path.c_str())->getSurf()); | |||
| 27679 | Uint8 r, g, b, a; | |||
| 27680 | getColor(img->color, &r, &g, &b, &a); | |||
| 27681 | if ( EnemyHPDamageBarHandler::bEnemyBarSimpleBlit && a < 255 ) { continue; } | |||
| 27682 | SDL_SetSurfaceAlphaMod(srcSurf, a * frameOpacity); | |||
| 27683 | SDL_Rect pos = img->pos; | |||
| 27684 | pos.x += skullFrame->getSize().x; | |||
| 27685 | pos.y += skullFrame->getSize().y; | |||
| 27686 | pos.y += statusEffectOffsetY; | |||
| 27687 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, sprite, &pos); | |||
| 27688 | } | |||
| 27689 | for ( auto& txt : frame->getFields() ) | |||
| 27690 | { | |||
| 27691 | auto textGet = Text::get(txt->getText(), txt->getFont(), | |||
| 27692 | makeColor(255, 255, 255, 255), makeColor(0, 0, 0, 255)); | |||
| 27693 | SDL_Surface* txtSurf = const_cast<SDL_Surface*>(textGet->getSurf()); | |||
| 27694 | SDL_Rect pos; | |||
| 27695 | pos.w = textGet->getWidth(); | |||
| 27696 | pos.h = textGet->getHeight(); | |||
| 27697 | pos.x = sprite->w / 2 - pos.w / 2; | |||
| 27698 | pos.y = frame->getSize().h / 2 - pos.h / 2; | |||
| 27699 | pos.y += statusEffectOffsetY; | |||
| 27700 | Uint8 r, g, b, a; | |||
| 27701 | getColor(txt->getColor(), &r, &g, &b, &a); | |||
| 27702 | SDL_SetSurfaceAlphaMod(txtSurf, a * frameOpacity); | |||
| 27703 | SDL_BlitSurfaceSDL_UpperBlit(txtSurf, nullptr, sprite, &pos); | |||
| 27704 | } | |||
| 27705 | if ( statusEffectSprite ) | |||
| 27706 | { | |||
| 27707 | int status_x = (sprite->w / 2) - (statusEffectSprite->w / 2); | |||
| 27708 | SDL_Rect pos{ status_x, 0, statusEffectSprite->w, statusEffectSprite->h}; | |||
| 27709 | SDL_BlitSurfaceSDL_UpperBlit(statusEffectSprite, nullptr, sprite, &pos); | |||
| 27710 | } | |||
| 27711 | ||||
| 27712 | if ( !hashSurf && EnemyHPDamageBarHandler::bEnemyBarSimpleBlit ) | |||
| 27713 | { | |||
| 27714 | enemyBarMapInsert(nameField->getText(), | |||
| 27715 | totalWidth, totalHeight, | |||
| 27716 | dmgProgress->pos.w, hpProgress->pos.w, | |||
| 27717 | enemy_statusEffects1, | |||
| 27718 | enemy_statusEffects2, | |||
| 27719 | enemy_statusEffectsLowDuration1, | |||
| 27720 | enemy_statusEffectsLowDuration2, | |||
| 27721 | sprite); | |||
| 27722 | } | |||
| 27723 | return sprite; | |||
| 27724 | } | |||
| 27725 | ||||
| 27726 | SDL_Surface* EnemyHPDamageBarHandler::EnemyHPDetails::blitEnemyBarStatusEffects(const int player) | |||
| 27727 | { | |||
| 27728 | Entity* entity = uidToEntity(enemy_uid); | |||
| 27729 | if ( entity && (entity->behavior != &actPlayer && entity->behavior != &actMonster) ) | |||
| 27730 | { | |||
| 27731 | return nullptr; | |||
| 27732 | } | |||
| 27733 | Frame* frame = players[player]->hud.enemyBarFrame; | |||
| 27734 | if ( !frame || !players[player]->isLocalPlayer() ) | |||
| 27735 | { | |||
| 27736 | return nullptr; | |||
| 27737 | } | |||
| 27738 | if ( enemy_statusEffects1 == 0 && enemy_statusEffects2 == 0 ) | |||
| 27739 | { | |||
| 27740 | return nullptr; | |||
| 27741 | } | |||
| 27742 | //auto baseBg = frame->findImage("base img"); | |||
| 27743 | //auto baseEndCap = frame->findImage("base img endcap"); | |||
| 27744 | //const int maxWidth = baseBg->pos.x + baseBg->pos.w + baseEndCap->pos.w; | |||
| 27745 | const int iconHeight = 32; | |||
| 27746 | const int iconWidth = 32; | |||
| 27747 | ||||
| 27748 | SDL_Surface* hashSurf = nullptr; | |||
| 27749 | if ( EnemyHPDamageBarHandler::bEnemyBarSimpleBlit ) | |||
| 27750 | { | |||
| 27751 | hashSurf = enemyBarEffectMapExists( | |||
| 27752 | enemy_statusEffects1, | |||
| 27753 | enemy_statusEffects2, | |||
| 27754 | enemy_statusEffectsLowDuration1, | |||
| 27755 | enemy_statusEffectsLowDuration2, | |||
| 27756 | (ticks % 25) >= 12); | |||
| 27757 | if ( !hashSurf ) | |||
| 27758 | { | |||
| 27759 | //messagePlayer(0, MESSAGE_DEBUG, "Hash for enemy effects not found!"); | |||
| 27760 | } | |||
| 27761 | else | |||
| 27762 | { | |||
| 27763 | return hashSurf; | |||
| 27764 | } | |||
| 27765 | } | |||
| 27766 | ||||
| 27767 | int playernum = -1; | |||
| 27768 | if ( entity && entity->behavior == &actPlayer ) | |||
| 27769 | { | |||
| 27770 | playernum = entity->skill[2]; | |||
| 27771 | } | |||
| 27772 | ||||
| 27773 | int currentX = 0; // (maxWidth / 2); | |||
| 27774 | bool anyStatusEffect = false; | |||
| 27775 | ||||
| 27776 | std::vector<std::pair<SDL_Surface*, bool>> statusEffectIcons; | |||
| 27777 | if ( enemy_statusEffects1 != 0 ) | |||
| 27778 | { | |||
| 27779 | for ( int i = 0; i < 32; ++i ) | |||
| 27780 | { | |||
| 27781 | if ( (enemy_statusEffects1 & (1 << i)) != 0 ) | |||
| 27782 | { | |||
| 27783 | if ( StatusEffectQueue_t::StatusEffectDefinitions_t::effectDefinitionExists(i) ) | |||
| 27784 | { | |||
| 27785 | int variation = -1; | |||
| 27786 | SDL_Surface* srcSurf = nullptr; | |||
| 27787 | if ( i == EFF_SHAPESHIFT ) | |||
| 27788 | { | |||
| 27789 | if ( entity && entity->behavior == &actPlayer ) | |||
| 27790 | { | |||
| 27791 | switch ( entity->effectShapeshift ) | |||
| 27792 | { | |||
| 27793 | case RAT: | |||
| 27794 | variation = 0; | |||
| 27795 | break; | |||
| 27796 | case SPIDER: | |||
| 27797 | variation = 1; | |||
| 27798 | break; | |||
| 27799 | case TROLL: | |||
| 27800 | variation = 2; | |||
| 27801 | break; | |||
| 27802 | case CREATURE_IMP: | |||
| 27803 | variation = 3; | |||
| 27804 | break; | |||
| 27805 | default: | |||
| 27806 | break; | |||
| 27807 | } | |||
| 27808 | } | |||
| 27809 | } | |||
| 27810 | auto& definition = StatusEffectQueue_t::StatusEffectDefinitions_t::getEffect(i); | |||
| 27811 | if ( !definition.neverDisplay ) | |||
| 27812 | { | |||
| 27813 | std::string imgPath; | |||
| 27814 | if ( i == EFF_SHAPESHIFT && variation == -1 ) | |||
| 27815 | { | |||
| 27816 | imgPath = ""; | |||
| 27817 | } | |||
| 27818 | else | |||
| 27819 | { | |||
| 27820 | imgPath = StatusEffectQueue_t::StatusEffectDefinitions_t::getEffectImgPath(definition, variation); | |||
| 27821 | } | |||
| 27822 | if ( imgPath != "" ) | |||
| 27823 | { | |||
| 27824 | srcSurf = const_cast<SDL_Surface*>(Image::get(imgPath.c_str())->getSurf()); | |||
| 27825 | ||||
| 27826 | bool blinking = false; | |||
| 27827 | if ( (enemy_statusEffectsLowDuration1 & (1 << i)) != 0 ) | |||
| 27828 | { | |||
| 27829 | blinking = true; | |||
| 27830 | } | |||
| 27831 | statusEffectIcons.push_back(std::make_pair(srcSurf, blinking)); | |||
| 27832 | } | |||
| 27833 | } | |||
| 27834 | } | |||
| 27835 | } | |||
| 27836 | } | |||
| 27837 | } | |||
| 27838 | if ( enemy_statusEffects2 != 0 ) | |||
| 27839 | { | |||
| 27840 | for ( int i = 0; i < 32; ++i ) | |||
| 27841 | { | |||
| 27842 | if ( (enemy_statusEffects2 & (1 << i)) != 0 ) | |||
| 27843 | { | |||
| 27844 | int effectID = i + 32; | |||
| 27845 | if ( StatusEffectQueue_t::StatusEffectDefinitions_t::effectDefinitionExists(effectID) ) | |||
| 27846 | { | |||
| 27847 | int variation = -1; | |||
| 27848 | SDL_Surface* srcSurf = nullptr; | |||
| 27849 | if ( i == EFF_SHAPESHIFT ) | |||
| 27850 | { | |||
| 27851 | if ( entity && entity->behavior == &actPlayer ) | |||
| 27852 | { | |||
| 27853 | switch ( entity->effectShapeshift ) | |||
| 27854 | { | |||
| 27855 | case RAT: | |||
| 27856 | variation = 0; | |||
| 27857 | break; | |||
| 27858 | case SPIDER: | |||
| 27859 | variation = 1; | |||
| 27860 | break; | |||
| 27861 | case TROLL: | |||
| 27862 | variation = 2; | |||
| 27863 | break; | |||
| 27864 | case CREATURE_IMP: | |||
| 27865 | variation = 3; | |||
| 27866 | break; | |||
| 27867 | default: | |||
| 27868 | break; | |||
| 27869 | } | |||
| 27870 | } | |||
| 27871 | } | |||
| 27872 | auto& definition = StatusEffectQueue_t::StatusEffectDefinitions_t::getEffect(effectID); | |||
| 27873 | if ( !definition.neverDisplay ) | |||
| 27874 | { | |||
| 27875 | std::string imgPath; | |||
| 27876 | if ( i == EFF_SHAPESHIFT && variation == -1 ) | |||
| 27877 | { | |||
| 27878 | imgPath = ""; | |||
| 27879 | } | |||
| 27880 | else | |||
| 27881 | { | |||
| 27882 | imgPath = StatusEffectQueue_t::StatusEffectDefinitions_t::getEffectImgPath(definition, variation); | |||
| 27883 | } | |||
| 27884 | if ( imgPath != "" ) | |||
| 27885 | { | |||
| 27886 | srcSurf = const_cast<SDL_Surface*>(Image::get(imgPath.c_str())->getSurf()); | |||
| 27887 | ||||
| 27888 | bool blinking = false; | |||
| 27889 | if ( (enemy_statusEffectsLowDuration2 & (1 << i)) != 0 ) | |||
| 27890 | { | |||
| 27891 | blinking = true; | |||
| 27892 | } | |||
| 27893 | statusEffectIcons.push_back(std::make_pair(srcSurf, blinking)); | |||
| 27894 | } | |||
| 27895 | } | |||
| 27896 | } | |||
| 27897 | } | |||
| 27898 | } | |||
| 27899 | } | |||
| 27900 | ||||
| 27901 | //const int numIcons = statusEffectIcons.size(); | |||
| 27902 | //const int iconTotalWidth = iconWidth + 2; | |||
| 27903 | //if ( numIcons % 2 == 1 ) // odd numbered | |||
| 27904 | //{ | |||
| 27905 | // currentX -= ((iconTotalWidth) * (numIcons / 2)) + (iconTotalWidth / 2); | |||
| 27906 | //} | |||
| 27907 | //else | |||
| 27908 | //{ | |||
| 27909 | // currentX -= ((iconTotalWidth) * (numIcons / 2)); | |||
| 27910 | //} | |||
| 27911 | ||||
| 27912 | if ( statusEffectIcons.empty() ) | |||
| 27913 | { | |||
| 27914 | return nullptr; | |||
| 27915 | } | |||
| 27916 | ||||
| 27917 | SDL_Surface* sprite = SDL_CreateRGBSurface(0, (iconWidth + 2) * statusEffectIcons.size(), iconHeight + 2, 32, | |||
| 27918 | 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); | |||
| 27919 | ||||
| 27920 | for ( auto& icon : statusEffectIcons ) | |||
| 27921 | { | |||
| 27922 | anyStatusEffect = true; | |||
| 27923 | int tickModifier = ticks % 25; | |||
| 27924 | real_t alpha = 255; | |||
| 27925 | /*if ( !EnemyHPDamageBarHandler::bEnemyBarSimpleBlit ) | |||
| 27926 | { | |||
| 27927 | const real_t frameOpacity = frame->getOpacity() / 100.0; | |||
| 27928 | alpha *= frameOpacity; | |||
| 27929 | }*/ | |||
| 27930 | if ( tickModifier >= 12 && icon.second ) | |||
| 27931 | { | |||
| 27932 | alpha = 0; | |||
| 27933 | } | |||
| 27934 | SDL_SetSurfaceAlphaMod(icon.first, alpha); | |||
| 27935 | //SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 27936 | SDL_Rect pos{ currentX, 0, iconWidth, iconHeight }; | |||
| 27937 | SDL_BlitScaledSDL_UpperBlitScaled(icon.first, nullptr, sprite, &pos); | |||
| 27938 | currentX += (iconWidth + 2); | |||
| 27939 | } | |||
| 27940 | ||||
| 27941 | if ( !hashSurf && EnemyHPDamageBarHandler::bEnemyBarSimpleBlit ) | |||
| 27942 | { | |||
| 27943 | enemyBarEffectMapInsert( | |||
| 27944 | enemy_statusEffects1, | |||
| 27945 | enemy_statusEffects2, | |||
| 27946 | enemy_statusEffectsLowDuration1, | |||
| 27947 | enemy_statusEffectsLowDuration2, | |||
| 27948 | (ticks % 25) >= 12, | |||
| 27949 | sprite); | |||
| 27950 | } | |||
| 27951 | return sprite; | |||
| 27952 | } | |||
| 27953 | ||||
| 27954 | EnemyHPDamageBarHandler::EnemyHPDetails::~EnemyHPDetails() | |||
| 27955 | { | |||
| 27956 | if ( worldTexture ) | |||
| 27957 | { | |||
| 27958 | delete worldTexture; | |||
| 27959 | worldTexture = nullptr; | |||
| 27960 | } | |||
| 27961 | if ( !bEnemyBarSimpleBlit ) | |||
| 27962 | { | |||
| 27963 | if ( worldSurfaceSpriteStatusEffects ) { | |||
| 27964 | SDL_FreeSurface(worldSurfaceSpriteStatusEffects); | |||
| 27965 | worldSurfaceSpriteStatusEffects = nullptr; | |||
| 27966 | } | |||
| 27967 | if ( worldSurfaceSprite ) { | |||
| 27968 | SDL_FreeSurface(worldSurfaceSprite); | |||
| 27969 | worldSurfaceSprite = nullptr; | |||
| 27970 | } | |||
| 27971 | } | |||
| 27972 | } | |||
| 27973 | ||||
| 27974 | void Player::HUD_t::updateEnemyBar2(Frame* whichFrame, void* enemyHPDetails) | |||
| 27975 | { | |||
| 27976 | if ( !whichFrame ) | |||
| 27977 | { | |||
| 27978 | return; | |||
| 27979 | } | |||
| 27980 | ||||
| 27981 | if ( !enemyHPDetails ) | |||
| 27982 | { | |||
| 27983 | return; | |||
| 27984 | } | |||
| 27985 | ||||
| 27986 | if ( !player.isLocalPlayer() ) | |||
| 27987 | { | |||
| 27988 | return; | |||
| 27989 | } | |||
| 27990 | ||||
| 27991 | EnemyHPDamageBarHandler::EnemyHPDetails* enemyDetails = static_cast<EnemyHPDamageBarHandler::EnemyHPDetails*>(enemyHPDetails); | |||
| 27992 | ||||
| 27993 | Entity* entity = uidToEntity(enemyDetails->enemy_uid); | |||
| 27994 | if ( entity ) | |||
| 27995 | { | |||
| 27996 | //enemyDetails->updateWorldCoordinates(); --moved to main loop before drawEntities3D | |||
| 27997 | if ( entity->behavior == &actMonster && entity->getMonsterTypeFromSprite() == MIMIC ) | |||
| 27998 | { | |||
| 27999 | if ( entity->isInertMimic() ) | |||
| 28000 | { | |||
| 28001 | enemyDetails->barType = EnemyHPDamageBarHandler::BAR_TYPE_FURNITURE; | |||
| 28002 | } | |||
| 28003 | else | |||
| 28004 | { | |||
| 28005 | enemyDetails->barType = EnemyHPDamageBarHandler::BAR_TYPE_CREATURE; | |||
| 28006 | } | |||
| 28007 | } | |||
| 28008 | } | |||
| 28009 | else | |||
| 28010 | { | |||
| 28011 | enemyDetails->enemy_hp = 0; | |||
| 28012 | } | |||
| 28013 | ||||
| 28014 | bool bIsMostRecentHPBar = enemyHPDamageBarHandler[player.playernum].getMostRecentHPBar() == enemyDetails; | |||
| 28015 | //if ( bIsMostRecentHPBar && !enemyDetails->hasDistanceCheck ) | |||
| 28016 | //{ | |||
| 28017 | // //enemyDetails->hasDistanceCheck = true; | |||
| 28018 | // auto& camera = cameras[player.playernum]; | |||
| 28019 | // double playerdist = sqrt(pow(camera.x * 16.0 - enemyDetails->worldX, 2) + pow(camera.y * 16.0 - enemyDetails->worldY, 2)); | |||
| 28020 | // if ( playerdist >= 3 * 16.0 ) | |||
| 28021 | // { | |||
| 28022 | // //enemyDetails->displayOnHUD = true; | |||
| 28023 | // } | |||
| 28024 | //} | |||
| 28025 | ||||
| 28026 | SDL_Rect pos = whichFrame->getSize(); | |||
| 28027 | bool doFadeout = false; | |||
| 28028 | bool doAnimation = true; | |||
| 28029 | if ( enemyDetails->displayOnHUD && whichFrame == enemyBarFrameHUD ) | |||
| 28030 | { | |||
| 28031 | doAnimation = false; | |||
| 28032 | } | |||
| 28033 | ||||
| 28034 | if ( gamePaused && multiplayer == SINGLE0 ) | |||
| 28035 | { | |||
| 28036 | enemyDetails->enemy_timer = ticks; | |||
| 28037 | return; | |||
| 28038 | } | |||
| 28039 | ||||
| 28040 | if ( doAnimation && !enemyDetails->displayOnHUD && !enemyDetails->expired && enemyDetails->animator.setpoint <= 0 ) | |||
| 28041 | { | |||
| 28042 | if ( ticks - enemyDetails->enemy_timer >= EnemyHPDamageBarHandler::shortDistanceHPBarFadeTicks ) | |||
| 28043 | { | |||
| 28044 | if ( splitscreen ) | |||
| 28045 | { | |||
| 28046 | // if anyone in splitscreen is near the bar, expire it instead of just the owner | |||
| 28047 | for ( int i = 0; i < MAXPLAYERS4; ++i ) | |||
| 28048 | { | |||
| 28049 | if ( i == player.playernum || players[i]->isLocalPlayerAlive() ) | |||
| 28050 | { | |||
| 28051 | auto& camera = cameras[i]; | |||
| 28052 | double playerdist = sqrt(pow(camera.x * 16.0 - enemyDetails->worldX, 2) + pow(camera.y * 16.0 - enemyDetails->worldY, 2)); | |||
| 28053 | if ( playerdist <= EnemyHPDamageBarHandler::shortDistanceHPBarFadeDistance * 16.0 ) | |||
| 28054 | { | |||
| 28055 | enemyDetails->expired = true; | |||
| 28056 | break; | |||
| 28057 | } | |||
| 28058 | } | |||
| 28059 | } | |||
| 28060 | } | |||
| 28061 | else | |||
| 28062 | { | |||
| 28063 | auto& camera = cameras[player.playernum]; | |||
| 28064 | double playerdist = sqrt(pow(camera.x * 16.0 - enemyDetails->worldX, 2) + pow(camera.y * 16.0 - enemyDetails->worldY, 2)); | |||
| 28065 | if ( playerdist <= EnemyHPDamageBarHandler::shortDistanceHPBarFadeDistance * 16.0 ) | |||
| 28066 | { | |||
| 28067 | enemyDetails->expired = true; | |||
| 28068 | } | |||
| 28069 | } | |||
| 28070 | } | |||
| 28071 | } | |||
| 28072 | ||||
| 28073 | if ( enemyDetails->expired == true ) | |||
| 28074 | { | |||
| 28075 | doFadeout = true; | |||
| 28076 | } | |||
| 28077 | else | |||
| 28078 | { | |||
| 28079 | enemyDetails->animator.fadeOut = 100.0; | |||
| 28080 | } | |||
| 28081 | ||||
| 28082 | if ( doFadeout ) | |||
| 28083 | { | |||
| 28084 | if ( doAnimation ) | |||
| 28085 | { | |||
| 28086 | enemyDetails->animator.fadeOut -= 10.0 * getFPSScale(60.0); | |||
| 28087 | if ( enemyDetails->animator.fadeOut < 0.0 ) | |||
| 28088 | { | |||
| 28089 | enemyDetails->animator.fadeOut = 0.0; | |||
| 28090 | enemyDetails->animator.fadeIn = 0.0; | |||
| 28091 | } | |||
| 28092 | } | |||
| 28093 | whichFrame->setOpacity(enemyDetails->animator.fadeOut); | |||
| 28094 | } | |||
| 28095 | else | |||
| 28096 | { | |||
| 28097 | enemyDetails->animator.fadeIn = 100.0; | |||
| 28098 | whichFrame->setOpacity(enemyDetails->animator.fadeIn); | |||
| 28099 | } | |||
| 28100 | ||||
| 28101 | auto baseBg = whichFrame->findImage("base img"); | |||
| 28102 | auto baseEndCap = whichFrame->findImage("base img endcap"); | |||
| 28103 | ||||
| 28104 | auto foregroundFrame = whichFrame->findFrame("bar progress frame"); | |||
| 28105 | auto hpProgress = foregroundFrame->findImage("progress img"); | |||
| 28106 | auto hpProgressEndcap = foregroundFrame->findImage("progress img endcap"); | |||
| 28107 | ||||
| 28108 | auto dmgFrame = whichFrame->findFrame("bar dmg frame"); | |||
| 28109 | auto dmgProgress = dmgFrame->findImage("dmg img"); | |||
| 28110 | auto dmgEndCap = dmgFrame->findImage("dmg img endcap"); | |||
| 28111 | //auto bubblesImg = dmgFrame->findImage("img bubbles"); | |||
| 28112 | ||||
| 28113 | real_t progressWidth = ENEMYBAR_BAR_WIDTH - hpProgressEndcap->pos.w; | |||
| 28114 | int backgroundWidth = ENEMYBAR_BAR_WIDTH - baseEndCap->pos.w; | |||
| 28115 | ||||
| 28116 | auto nameTxt = whichFrame->findField("enemy name txt"); | |||
| 28117 | ||||
| 28118 | // handle bar size changing | |||
| 28119 | { | |||
| 28120 | std::vector<std::pair<real_t, int>> widthHealthBreakpoints; | |||
| 28121 | if ( enemyDetails->barType == EnemyHPDamageBarHandler::BAR_TYPE_CREATURE ) | |||
| 28122 | { | |||
| 28123 | widthHealthBreakpoints = EnemyHPDamageBarHandler::widthHealthBreakpointsMonsters; | |||
| 28124 | } | |||
| 28125 | else | |||
| 28126 | { | |||
| 28127 | widthHealthBreakpoints = EnemyHPDamageBarHandler::widthHealthBreakpointsFurniture; | |||
| 28128 | } | |||
| 28129 | if ( widthHealthBreakpoints.empty() ) // width %, then HP value | |||
| 28130 | { | |||
| 28131 | // build some defaults | |||
| 28132 | widthHealthBreakpoints.push_back(std::make_pair(0.5, 10)); | |||
| 28133 | widthHealthBreakpoints.push_back(std::make_pair(0.60, 20)); | |||
| 28134 | widthHealthBreakpoints.push_back(std::make_pair(0.70, 50)); | |||
| 28135 | widthHealthBreakpoints.push_back(std::make_pair(0.80, 100)); | |||
| 28136 | widthHealthBreakpoints.push_back(std::make_pair(0.90, 250)); | |||
| 28137 | widthHealthBreakpoints.push_back(std::make_pair(1.00, 1000)); | |||
| 28138 | } | |||
| 28139 | ||||
| 28140 | enemyDetails->animator.widthMultiplier = 1.0; | |||
| 28141 | auto prevIt = widthHealthBreakpoints.end(); | |||
| 28142 | bool foundBreakpoint = false; | |||
| 28143 | for ( auto it = widthHealthBreakpoints.begin(); it != widthHealthBreakpoints.end(); ++it ) | |||
| 28144 | { | |||
| 28145 | int healthThreshold = (*it).second; | |||
| 28146 | real_t widthEntry = (*it).first; | |||
| 28147 | if ( (int)enemyDetails->animator.maxValue <= healthThreshold ) | |||
| 28148 | { | |||
| 28149 | real_t width = 0.0; | |||
| 28150 | if ( prevIt != widthHealthBreakpoints.end() ) | |||
| 28151 | { | |||
| 28152 | width = (*prevIt).first; | |||
| 28153 | // get linear scaled value between the breakponts | |||
| 28154 | width += (widthEntry - (*prevIt).first) * ((int)enemyDetails->animator.maxValue - (*prevIt).second) / ((*it).second - (*prevIt).second); | |||
| 28155 | } | |||
| 28156 | else | |||
| 28157 | { | |||
| 28158 | // set as minimum width | |||
| 28159 | width = widthEntry; | |||
| 28160 | } | |||
| 28161 | enemyDetails->animator.widthMultiplier = width; | |||
| 28162 | foundBreakpoint = true; | |||
| 28163 | break; | |||
| 28164 | } | |||
| 28165 | prevIt = it; | |||
| 28166 | } | |||
| 28167 | if ( !foundBreakpoint ) | |||
| 28168 | { | |||
| 28169 | enemyDetails->animator.widthMultiplier = widthHealthBreakpoints[widthHealthBreakpoints.size() - 1].first; | |||
| 28170 | } | |||
| 28171 | ||||
| 28172 | real_t multiplier = enemyDetails->animator.widthMultiplier; | |||
| 28173 | ||||
| 28174 | int diff = static_cast<int>(std::max(0.0, progressWidth - progressWidth * multiplier)); // how many pixels the progress bar shrinks | |||
| 28175 | progressWidth *= multiplier; // scale the progress bars | |||
| 28176 | baseBg->pos.w = backgroundWidth - diff; // move the background bar by x pixels | |||
| 28177 | baseEndCap->pos.x = baseBg->pos.x + baseBg->pos.w; // move the background endcap by the new width | |||
| 28178 | ||||
| 28179 | hpProgress->pos.w = progressWidth; | |||
| 28180 | hpProgressEndcap->pos.x = hpProgress->pos.x + hpProgress->pos.w; | |||
| 28181 | ||||
| 28182 | pos.x = (hudFrame->getSize().w / 2) - ENEMYBAR_FRAME_WIDTH / 2 - 6; | |||
| 28183 | int widthChange = ((ENEMYBAR_BAR_WIDTH - hpProgressEndcap->pos.w) - progressWidth); | |||
| 28184 | pos.x += widthChange / 2; | |||
| 28185 | SDL_Rect textPos = nameTxt->getSize(); | |||
| 28186 | textPos.w = ENEMYBAR_FRAME_WIDTH - widthChange; | |||
| 28187 | textPos.y = baseBg->pos.y; | |||
| 28188 | textPos.h = baseBg->pos.h; | |||
| 28189 | nameTxt->setSize(textPos); | |||
| 28190 | } | |||
| 28191 | ||||
| 28192 | int startY = hudFrame->getSize().h - ENEMYBAR_FRAME_START_Y - 100; | |||
| 28193 | if ( doFadeout ) | |||
| 28194 | { | |||
| 28195 | pos.y = startY + (15 * (100.0 - enemyDetails->animator.fadeOut) / 100.0); // slide out downwards | |||
| 28196 | } | |||
| 28197 | else | |||
| 28198 | { | |||
| 28199 | pos.y = startY; | |||
| 28200 | } | |||
| 28201 | whichFrame->setSize(pos); | |||
| 28202 | ||||
| 28203 | enemyDetails->animator.previousSetpoint = enemyDetails->animator.setpoint; | |||
| 28204 | real_t& hpForegroundValue = enemyDetails->animator.foregroundValue; | |||
| 28205 | real_t& hpFadedValue = enemyDetails->animator.backgroundValue; | |||
| 28206 | ||||
| 28207 | if ( doAnimation ) | |||
| 28208 | { | |||
| 28209 | enemyDetails->animator.setpoint = enemyDetails->enemy_hp; | |||
| 28210 | if ( enemyDetails->animator.setpoint < enemyDetails->animator.previousSetpoint ) // insta-change as losing health | |||
| 28211 | { | |||
| 28212 | hpForegroundValue = enemyDetails->animator.setpoint; | |||
| 28213 | enemyDetails->animator.animateTicks = ticks; | |||
| 28214 | } | |||
| 28215 | ||||
| 28216 | if ( enemyDetails->animator.maxValue > enemyDetails->enemy_maxhp ) | |||
| 28217 | { | |||
| 28218 | hpFadedValue = enemyDetails->animator.setpoint; // resetting game etc, stop fade animation sticking out of frame | |||
| 28219 | } | |||
| 28220 | enemyDetails->animator.maxValue = enemyDetails->enemy_maxhp; | |||
| 28221 | ||||
| 28222 | ||||
| 28223 | if ( hpForegroundValue < enemyDetails->animator.setpoint ) // gaining HP, animate | |||
| 28224 | { | |||
| 28225 | real_t setpointDiff = std::max(0.01, enemyDetails->animator.setpoint - hpForegroundValue); | |||
| 28226 | real_t fpsScale = getFPSScale(144.0); | |||
| 28227 | hpForegroundValue += fpsScale * (setpointDiff / 20.0); // reach it in 20 intervals, scaled to FPS | |||
| 28228 | hpForegroundValue = std::min(static_cast<real_t>(enemyDetails->animator.setpoint), hpForegroundValue); | |||
| 28229 | ||||
| 28230 | if ( abs(enemyDetails->animator.setpoint) - abs(hpForegroundValue) <= .05 ) | |||
| 28231 | { | |||
| 28232 | hpForegroundValue = enemyDetails->animator.setpoint; | |||
| 28233 | } | |||
| 28234 | } | |||
| 28235 | else if ( hpForegroundValue > enemyDetails->animator.setpoint ) // losing HP, snap to value | |||
| 28236 | { | |||
| 28237 | hpForegroundValue = enemyDetails->animator.setpoint; | |||
| 28238 | } | |||
| 28239 | ||||
| 28240 | if ( hpFadedValue < enemyDetails->animator.setpoint ) | |||
| 28241 | { | |||
| 28242 | hpFadedValue = hpForegroundValue; | |||
| 28243 | enemyDetails->animator.animateTicks = ticks; | |||
| 28244 | } | |||
| 28245 | else if ( hpFadedValue > enemyDetails->animator.setpoint ) | |||
| 28246 | { | |||
| 28247 | if ( ticks - enemyDetails->animator.animateTicks > 30 || enemyDetails->animator.setpoint <= 0 ) // fall after x ticks | |||
| 28248 | { | |||
| 28249 | real_t setpointDiff = std::max(0.01, hpFadedValue - enemyDetails->animator.setpoint); | |||
| 28250 | real_t fpsScale = getFPSScale(144.0); | |||
| 28251 | real_t intervals = 10.0; | |||
| 28252 | if ( enemyDetails->animator.setpoint <= 0 ) | |||
| 28253 | { | |||
| 28254 | intervals = 30.0; // dramatic | |||
| 28255 | } | |||
| 28256 | hpFadedValue -= fpsScale * (setpointDiff / intervals); // reach it in X intervals, scaled to FPS | |||
| 28257 | hpFadedValue = std::max(static_cast<real_t>(enemyDetails->animator.setpoint), hpFadedValue); | |||
| 28258 | } | |||
| 28259 | } | |||
| 28260 | else | |||
| 28261 | { | |||
| 28262 | enemyDetails->animator.animateTicks = ticks; | |||
| 28263 | } | |||
| 28264 | } | |||
| 28265 | ||||
| 28266 | auto skullFrame = whichFrame->findFrame("skull frame"); | |||
| 28267 | std::vector<std::pair<Frame::image_t*, int>> allSkulls; | |||
| 28268 | allSkulls.push_back(std::make_pair(skullFrame->findImage("skull 0 img"), 0)); | |||
| 28269 | allSkulls.push_back(std::make_pair(skullFrame->findImage("skull 25 img"), 25)); | |||
| 28270 | allSkulls.push_back(std::make_pair(skullFrame->findImage("skull 50 img"), 50)); | |||
| 28271 | allSkulls.push_back(std::make_pair(skullFrame->findImage("skull 100 img"), 75)); | |||
| 28272 | real_t healthPercentage = 100 * enemyDetails->animator.setpoint / std::max(1.0, enemyDetails->animator.maxValue); | |||
| 28273 | int skullIndex = 0; | |||
| 28274 | for ( auto& skull : allSkulls ) | |||
| 28275 | { | |||
| 28276 | if ( !skull.first ) { continue; } | |||
| 28277 | ||||
| 28278 | Uint8 r, g, b, a; | |||
| 28279 | getColor(skull.first->color, &r, &g, &b, &a); | |||
| 28280 | real_t& skullOpacity = enemyDetails->animator.skullOpacities[skullIndex]; | |||
| 28281 | ||||
| 28282 | if ( doAnimation ) | |||
| 28283 | { | |||
| 28284 | if ( (int)healthPercentage < skull.second ) | |||
| 28285 | { | |||
| 28286 | real_t opacityChange = 4 * getFPSScale(60.0); // change independent of fps | |||
| 28287 | skullOpacity = std::max(0, (int)(skullOpacity - opacityChange)); | |||
| 28288 | } | |||
| 28289 | else if ( (int)healthPercentage >= skull.second ) | |||
| 28290 | { | |||
| 28291 | real_t opacityChange = 255;// *getFPSScale(144.0); // change independent of fps | |||
| 28292 | skullOpacity = std::min(255, (int)(skullOpacity + opacityChange)); | |||
| 28293 | } | |||
| 28294 | } | |||
| 28295 | a = skullOpacity; | |||
| 28296 | //a *= enemyDetails->animator.fadeOut / 100.0; | |||
| 28297 | skull.first->color = makeColor( r, g, b, a); | |||
| 28298 | ++skullIndex; | |||
| 28299 | } | |||
| 28300 | ||||
| 28301 | nameTxt->setText(enemyDetails->enemy_name.c_str()); | |||
| 28302 | ||||
| 28303 | real_t foregroundPercent = hpForegroundValue / enemyDetails->animator.maxValue; | |||
| 28304 | hpProgress->pos.w = std::max(1, static_cast<int>((progressWidth)* foregroundPercent)); | |||
| 28305 | hpProgressEndcap->pos.x = hpProgress->pos.x + hpProgress->pos.w; | |||
| 28306 | ||||
| 28307 | real_t fadePercent = hpFadedValue / enemyDetails->animator.maxValue; | |||
| 28308 | dmgProgress->pos.w = std::max(1, static_cast<int>((progressWidth)* fadePercent)); | |||
| 28309 | dmgEndCap->pos.x = dmgProgress->pos.x + dmgProgress->pos.w; | |||
| 28310 | if ( dmgProgress->pos.w == 1 && enemyDetails->animator.setpoint <= 0 ) | |||
| 28311 | { | |||
| 28312 | dmgProgress->disabled = true; | |||
| 28313 | //real_t& opacity = enemyDetails->animator.damageFrameOpacity; | |||
| 28314 | //if ( doAnimation ) | |||
| 28315 | //{ | |||
| 28316 | // real_t opacityChange = .5 * getFPSScale(144.0); // change by .05% independent of fps | |||
| 28317 | // opacity = std::max(0.0, opacity - opacityChange); | |||
| 28318 | //} | |||
| 28319 | //dmgFrame->setOpacity(opacity); | |||
| 28320 | //dmgFrame->setOpacity(dmgFrame->getOpacity() * enemyDetails->animator.fadeOut / 100.0); | |||
| 28321 | //// make this element fade out to the left | |||
| 28322 | //dmgEndCap->pos.x = 0 - (dmgEndCap->pos.w * (1.0 - opacity / 100.0)); | |||
| 28323 | } | |||
| 28324 | else | |||
| 28325 | { | |||
| 28326 | dmgProgress->disabled = false; | |||
| 28327 | enemyDetails->animator.damageFrameOpacity = enemyDetails->animator.fadeOut; | |||
| 28328 | dmgFrame->setOpacity(enemyDetails->animator.fadeOut); | |||
| 28329 | } | |||
| 28330 | ||||
| 28331 | if ( enemyDetails->animator.setpoint <= 0 ) | |||
| 28332 | { | |||
| 28333 | // hide all the progress elements when dead, as endcap/base don't shrink | |||
| 28334 | // hpProgress width 0px defaults to original size, so hide that too | |||
| 28335 | hpProgress->disabled = true; | |||
| 28336 | hpProgressEndcap->disabled = true; | |||
| 28337 | } | |||
| 28338 | else | |||
| 28339 | { | |||
| 28340 | hpProgress->disabled = false; | |||
| 28341 | hpProgressEndcap->disabled = false; | |||
| 28342 | } | |||
| 28343 | ||||
| 28344 | // damage number on HUD | |||
| 28345 | if ( enemyDetails->displayOnHUD && whichFrame == enemyBarFrameHUD ) | |||
| 28346 | { | |||
| 28347 | auto dmgText = hudFrame->findField("enemy dmg txt"); | |||
| 28348 | Sint32 damageNumber = enemyDetails->animator.damageTaken; | |||
| 28349 | enemyDetails->animator.damageTaken = -1; | |||
| 28350 | if ( damageNumber >= 0 ) | |||
| 28351 | { | |||
| 28352 | char buf[128] = ""; | |||
| 28353 | snprintf(buf, sizeof(buf), "%d", damageNumber); | |||
| 28354 | dmgText->setText(buf); | |||
| 28355 | dmgText->setDisabled(false); | |||
| 28356 | SDL_Rect txtPos = dmgText->getSize(); | |||
| 28357 | SDL_Rect barPos = foregroundFrame->getAbsoluteSize(); | |||
| 28358 | //txtPos.x = barPos.x + baseBg->pos.x/* + baseBg->pos.w*/; | |||
| 28359 | //txtPos.y = barPos.y - 30; | |||
| 28360 | auto text = Text::get(dmgText->getText(), dmgText->getFont(), | |||
| 28361 | makeColor(255, 255, 255, 255), makeColor(0, 0, 0, 255)); | |||
| 28362 | txtPos.x = 30 + player.camera_virtualWidth() / 2; | |||
| 28363 | txtPos.y = -50 + player.camera_virtualHeight() / 2; | |||
| 28364 | txtPos.w = text->getWidth(); | |||
| 28365 | txtPos.h = text->getHeight(); | |||
| 28366 | dmgText->setSize(txtPos); | |||
| 28367 | hudDamageTextVelocityX = 1.0; | |||
| 28368 | hudDamageTextVelocityY = 3.0; | |||
| 28369 | Uint8 r, g, b, a; | |||
| 28370 | getColor(dmgText->getColor(), &r, &g, &b, &a); | |||
| 28371 | dmgText->setColor(makeColor(r, g, b, 255)); | |||
| 28372 | } | |||
| 28373 | ||||
| 28374 | if ( !dmgText->isDisabled() ) | |||
| 28375 | { | |||
| 28376 | SDL_Rect txtPos = dmgText->getSize(); | |||
| 28377 | txtPos.x += hudDamageTextVelocityX; | |||
| 28378 | txtPos.y -= hudDamageTextVelocityY; | |||
| 28379 | hudDamageTextVelocityX += .05; | |||
| 28380 | hudDamageTextVelocityY -= .3; | |||
| 28381 | dmgText->setSize(txtPos); | |||
| 28382 | if ( hudDamageTextVelocityY < -2.0 ) | |||
| 28383 | { | |||
| 28384 | Uint8 r, g, b, a; | |||
| 28385 | getColor(dmgText->getColor(), &r, &g, &b, &a); | |||
| 28386 | a = (std::max(0, (int)a - 16)); | |||
| 28387 | dmgText->setColor(makeColor(r, g, b, a)); | |||
| 28388 | if ( a == 0 ) | |||
| 28389 | { | |||
| 28390 | dmgText->setDisabled(true); | |||
| 28391 | } | |||
| 28392 | } | |||
| 28393 | } | |||
| 28394 | } | |||
| 28395 | ||||
| 28396 | ||||
| 28397 | bool oldBlitType = EnemyHPDamageBarHandler::bEnemyBarSimpleBlit; | |||
| 28398 | EnemyHPDamageBarHandler::bEnemyBarSimpleBlit = *cvar_enemybar_simple_blit; | |||
| 28399 | ||||
| 28400 | //auto blit = std::chrono::high_resolution_clock::now(); | |||
| 28401 | if ( !EnemyHPDamageBarHandler::bEnemyBarSimpleBlit ) | |||
| 28402 | { | |||
| 28403 | if ( !enemyBarMap.m.empty() ) | |||
| 28404 | { | |||
| 28405 | enemyBarEffectMap.m.clear(); | |||
| 28406 | enemyBarMap.m.clear(); | |||
| 28407 | enemyDetails->worldSurfaceSprite = nullptr; | |||
| 28408 | enemyDetails->worldSurfaceSpriteStatusEffects = nullptr; | |||
| 28409 | } | |||
| 28410 | ||||
| 28411 | if ( enemyDetails->worldTexture ) | |||
| 28412 | { | |||
| 28413 | delete enemyDetails->worldTexture; | |||
| 28414 | enemyDetails->worldTexture = nullptr; | |||
| 28415 | } | |||
| 28416 | if ( enemyDetails->worldSurfaceSprite ) | |||
| 28417 | { | |||
| 28418 | SDL_FreeSurface(enemyDetails->worldSurfaceSprite); | |||
| 28419 | enemyDetails->worldSurfaceSprite = nullptr; | |||
| 28420 | } | |||
| 28421 | if ( enemyDetails->worldSurfaceSpriteStatusEffects ) | |||
| 28422 | { | |||
| 28423 | SDL_FreeSurface(enemyDetails->worldSurfaceSpriteStatusEffects); | |||
| 28424 | enemyDetails->worldSurfaceSpriteStatusEffects = nullptr; | |||
| 28425 | } | |||
| 28426 | ||||
| 28427 | enemyDetails->worldSurfaceSpriteStatusEffects = enemyDetails->blitEnemyBarStatusEffects(player.playernum); | |||
| 28428 | //auto blit2 = std::chrono::high_resolution_clock::now(); | |||
| 28429 | enemyDetails->worldSurfaceSprite = enemyDetails->blitEnemyBar(player.playernum, enemyDetails->worldSurfaceSpriteStatusEffects); | |||
| 28430 | //auto blit3 = std::chrono::high_resolution_clock::now(); | |||
| 28431 | enemyDetails->worldTexture = new TempTexture(); | |||
| 28432 | enemyDetails->worldTexture->load(enemyDetails->worldSurfaceSprite, false, true); | |||
| 28433 | //auto blit4 = std::chrono::high_resolution_clock::now(); | |||
| 28434 | //float ms1 = 1000 * std::chrono::duration_cast<std::chrono::duration<double>>(blit2 - blit).count(); | |||
| 28435 | //float ms2 = 1000 * std::chrono::duration_cast<std::chrono::duration<double>>(blit3 - blit2).count(); | |||
| 28436 | //float ms3 = 1000 * std::chrono::duration_cast<std::chrono::duration<double>>(blit4 - blit3).count(); | |||
| 28437 | //float msTotal = 1000 * std::chrono::duration_cast<std::chrono::duration<double>>(blit4 - blit).count(); | |||
| 28438 | //printTextFormatted(font16x16_bmp, 8, 8 + 4 * 16, "Total: %.4f\n ms1: %.4f\n ms2: %.4f\nms3: %.4f", msTotal, ms1, ms2, ms3); | |||
| 28439 | } | |||
| 28440 | else | |||
| 28441 | { | |||
| 28442 | enemyDetails->worldSurfaceSpriteStatusEffects = enemyDetails->blitEnemyBarStatusEffects(player.playernum); | |||
| 28443 | //auto blit2 = std::chrono::high_resolution_clock::now(); | |||
| 28444 | SDL_Surface* oldWorldSprite = enemyDetails->worldSurfaceSprite; | |||
| 28445 | enemyDetails->worldSurfaceSprite = enemyDetails->blitEnemyBar(player.playernum, enemyDetails->worldSurfaceSpriteStatusEffects); | |||
| 28446 | //auto blit3 = std::chrono::high_resolution_clock::now(); | |||
| 28447 | if ( oldWorldSprite != enemyDetails->worldSurfaceSprite ) | |||
| 28448 | { | |||
| 28449 | if ( enemyDetails->worldTexture ) | |||
| 28450 | { | |||
| 28451 | delete enemyDetails->worldTexture; | |||
| 28452 | enemyDetails->worldTexture = nullptr; | |||
| 28453 | } | |||
| 28454 | ||||
| 28455 | if ( enemyDetails->worldSurfaceSprite ) | |||
| 28456 | { | |||
| 28457 | enemyDetails->worldTexture = new TempTexture(); | |||
| 28458 | enemyDetails->worldTexture->load(enemyDetails->worldSurfaceSprite, false, true); | |||
| 28459 | } | |||
| 28460 | } | |||
| 28461 | //auto blit4 = std::chrono::high_resolution_clock::now(); | |||
| 28462 | //float ms1 = 1000 * std::chrono::duration_cast<std::chrono::duration<double>>(blit2 - blit).count(); | |||
| 28463 | //float ms2 = 1000 * std::chrono::duration_cast<std::chrono::duration<double>>(blit3 - blit2).count(); | |||
| 28464 | //float ms3 = 1000 * std::chrono::duration_cast<std::chrono::duration<double>>(blit4 - blit3).count(); | |||
| 28465 | //float msTotal = 1000 * std::chrono::duration_cast<std::chrono::duration<double>>(blit4 - blit).count(); | |||
| 28466 | //printTextFormatted(font16x16_bmp, 8, 8 + 4 * 16, "Total: %.4f\n ms1: %.4f\n ms2: %.4f\nms3: %.4f", msTotal, ms1, ms2, ms3); | |||
| 28467 | } | |||
| 28468 | ||||
| 28469 | ||||
| 28470 | ||||
| 28471 | whichFrame->setDisabled(true); | |||
| 28472 | if ( !enemyDetails->displayOnHUD ) | |||
| 28473 | { | |||
| 28474 | //printTextFormatted(font16x16_bmp, 8, 8 + 4 * 16, "Any vertex visible: %d", anyVertexVisible); | |||
| 28475 | } | |||
| 28476 | else | |||
| 28477 | { | |||
| 28478 | if ( whichFrame == enemyBarFrameHUD ) | |||
| 28479 | { | |||
| 28480 | whichFrame->setDisabled(false); | |||
| 28481 | } | |||
| 28482 | else | |||
| 28483 | { | |||
| 28484 | updateEnemyBar2(enemyBarFrameHUD, enemyHPDetails); | |||
| 28485 | } | |||
| 28486 | } | |||
| 28487 | } | |||
| 28488 | ||||
| 28489 | static ConsoleCommand ccmd_enemybar_dump_cache("/enemybar_dump_cache", "Dumps cached enemy bars", | |||
| 28490 | [](int argc, const char** argv) { | |||
| 28491 | EnemyHPDamageBarHandler::dumpCache(); | |||
| 28492 | }); | |||
| 28493 | ||||
| 28494 | void EnemyHPDamageBarHandler::dumpCache() | |||
| 28495 | { | |||
| 28496 | enemyBarEffectMap.m.clear(); | |||
| 28497 | enemyBarMap.m.clear(); | |||
| 28498 | for ( int i = 0; i < MAXPLAYERS4; ++i ) | |||
| 28499 | { | |||
| 28500 | enemyHPDamageBarHandler[i].HPBars.clear(); | |||
| 28501 | } | |||
| 28502 | } | |||
| 28503 | ||||
| 28504 | void Player::HUD_t::updateEnemyBar(Frame* whichFrame) | |||
| 28505 | { | |||
| 28506 | if ( !whichFrame ) | |||
| 28507 | { | |||
| 28508 | return; | |||
| 28509 | } | |||
| 28510 | ||||
| 28511 | if ( !player.isLocalPlayer() ) | |||
| 28512 | { | |||
| 28513 | return; | |||
| 28514 | } | |||
| 28515 | ||||
| 28516 | SDL_Rect pos = whichFrame->getSize(); | |||
| 28517 | bool doFadeout = false; | |||
| 28518 | ||||
| 28519 | EnemyHPDamageBarHandler::EnemyHPDetails* enemyDetails = nullptr; | |||
| 28520 | Bar_t* enemyBar = nullptr; | |||
| 28521 | Sint32 damageNumber = -1; | |||
| 28522 | enemyDetails = enemyHPDamageBarHandler[player.playernum].getMostRecentHPBar(); | |||
| 28523 | enemyBar = &this->enemyBar; | |||
| 28524 | ||||
| 28525 | if ( enemyDetails ) | |||
| 28526 | { | |||
| 28527 | enemyBar->animatePreviousSetpoint = enemyDetails->animator.previousSetpoint; | |||
| 28528 | enemyBar->animateValue = enemyDetails->animator.foregroundValue; | |||
| 28529 | enemyBar->animateValue2 = enemyDetails->animator.backgroundValue; | |||
| 28530 | enemyBar->animateSetpoint = enemyDetails->animator.setpoint; | |||
| 28531 | enemyBar->animateTicks = enemyDetails->animator.animateTicks; | |||
| 28532 | enemyBar->maxValue = enemyDetails->animator.maxValue; | |||
| 28533 | enemyBar->fadeOut = 100.0; | |||
| 28534 | damageNumber = enemyDetails->animator.damageTaken; | |||
| 28535 | enemyDetails->animator.damageTaken = -1; | |||
| 28536 | ||||
| 28537 | if ( Entity* entity = uidToEntity(enemyDetails->enemy_uid) ) | |||
| 28538 | { | |||
| 28539 | enemyDetails->worldX = entity->x; | |||
| 28540 | enemyDetails->worldY = entity->y; | |||
| 28541 | enemyDetails->worldZ = entity->z; | |||
| 28542 | } | |||
| 28543 | } | |||
| 28544 | if ( !enemyDetails || enemyDetails->expired == true ) | |||
| 28545 | { | |||
| 28546 | doFadeout = true; | |||
| 28547 | } | |||
| 28548 | ||||
| 28549 | if ( doFadeout ) | |||
| 28550 | { | |||
| 28551 | enemyBar->fadeOut -= 10.0 * getFPSScale(60.0); | |||
| 28552 | if ( enemyBar->fadeOut < 0.0 ) { enemyBar->fadeOut = 0.0; enemyBar->fadeIn = 0.0; } | |||
| 28553 | whichFrame->setOpacity(enemyBar->fadeOut); | |||
| 28554 | } | |||
| 28555 | else | |||
| 28556 | { | |||
| 28557 | enemyBar->fadeIn = 100.0; | |||
| 28558 | whichFrame->setOpacity(enemyBar->fadeIn); | |||
| 28559 | } | |||
| 28560 | ||||
| 28561 | auto baseBg = whichFrame->findImage("base img"); | |||
| 28562 | auto baseEndCap = whichFrame->findImage("base img endcap"); | |||
| 28563 | ||||
| 28564 | auto foregroundFrame = whichFrame->findFrame("bar progress frame"); | |||
| 28565 | auto hpProgress = foregroundFrame->findImage("progress img"); | |||
| 28566 | auto hpProgressEndcap = foregroundFrame->findImage("progress img endcap"); | |||
| 28567 | ||||
| 28568 | auto dmgFrame = whichFrame->findFrame("bar dmg frame"); | |||
| 28569 | auto dmgProgress = dmgFrame->findImage("dmg img"); | |||
| 28570 | auto dmgEndCap = dmgFrame->findImage("dmg img endcap"); | |||
| 28571 | //auto bubblesImg = dmgFrame->findImage("img bubbles"); | |||
| 28572 | ||||
| 28573 | real_t progressWidth = ENEMYBAR_BAR_WIDTH - hpProgressEndcap->pos.w; | |||
| 28574 | int backgroundWidth = ENEMYBAR_BAR_WIDTH - baseEndCap->pos.w; | |||
| 28575 | ||||
| 28576 | auto nameTxt = whichFrame->findField("enemy name txt"); | |||
| 28577 | ||||
| 28578 | // handle bar size changing | |||
| 28579 | { | |||
| 28580 | std::vector<std::pair<real_t, int>>widthHealthBreakpoints; // width %, then HP value | |||
| 28581 | widthHealthBreakpoints.push_back(std::make_pair(0.5, 10)); | |||
| 28582 | widthHealthBreakpoints.push_back(std::make_pair(0.60, 20)); | |||
| 28583 | widthHealthBreakpoints.push_back(std::make_pair(0.70, 50)); | |||
| 28584 | widthHealthBreakpoints.push_back(std::make_pair(0.80, 100)); | |||
| 28585 | widthHealthBreakpoints.push_back(std::make_pair(0.90, 250)); | |||
| 28586 | widthHealthBreakpoints.push_back(std::make_pair(1.00, 1000)); | |||
| 28587 | ||||
| 28588 | enemyBar->widthMultiplier = 1.0; | |||
| 28589 | auto prevIt = widthHealthBreakpoints.end(); | |||
| 28590 | bool foundBreakpoint = false; | |||
| 28591 | for ( auto it = widthHealthBreakpoints.begin(); it != widthHealthBreakpoints.end(); ++it ) | |||
| 28592 | { | |||
| 28593 | int healthThreshold = (*it).second; | |||
| 28594 | real_t widthEntry = (*it).first; | |||
| 28595 | if ( (int)enemyBar->maxValue <= healthThreshold ) | |||
| 28596 | { | |||
| 28597 | real_t width = 0.0; | |||
| 28598 | if ( prevIt != widthHealthBreakpoints.end() ) | |||
| 28599 | { | |||
| 28600 | width = (*prevIt).first; | |||
| 28601 | // get linear scaled value between the breakponts | |||
| 28602 | width += (widthEntry - (*prevIt).first) * ((int)enemyBar->maxValue - (*prevIt).second) / ((*it).second - (*prevIt).second); | |||
| 28603 | } | |||
| 28604 | else | |||
| 28605 | { | |||
| 28606 | // set as minimum width | |||
| 28607 | width = widthEntry; /**((int)enemyBar->maxValue) / ((*it).second);*/ | |||
| 28608 | } | |||
| 28609 | enemyBar->widthMultiplier = width; | |||
| 28610 | foundBreakpoint = true; | |||
| 28611 | break; | |||
| 28612 | } | |||
| 28613 | prevIt = it; | |||
| 28614 | } | |||
| 28615 | if ( !foundBreakpoint ) | |||
| 28616 | { | |||
| 28617 | enemyBar->widthMultiplier = widthHealthBreakpoints[widthHealthBreakpoints.size() - 1].first; | |||
| 28618 | } | |||
| 28619 | ||||
| 28620 | real_t multiplier = enemyBar->widthMultiplier; | |||
| 28621 | ||||
| 28622 | int diff = static_cast<int>(std::max(0.0, progressWidth - progressWidth * multiplier)); // how many pixels the progress bar shrinks | |||
| 28623 | progressWidth *= multiplier; // scale the progress bars | |||
| 28624 | baseBg->pos.w = backgroundWidth - diff; // move the background bar by x pixels | |||
| 28625 | baseEndCap->pos.x = baseBg->pos.x + baseBg->pos.w; // move the background endcap by the new width | |||
| 28626 | ||||
| 28627 | hpProgress->pos.w = progressWidth; | |||
| 28628 | hpProgressEndcap->pos.x = hpProgress->pos.x + hpProgress->pos.w; | |||
| 28629 | ||||
| 28630 | pos.x = (hudFrame->getSize().w / 2) - ENEMYBAR_FRAME_WIDTH / 2 - 6; | |||
| 28631 | int widthChange = ((ENEMYBAR_BAR_WIDTH - hpProgressEndcap->pos.w) - progressWidth); | |||
| 28632 | pos.x += widthChange / 2; | |||
| 28633 | SDL_Rect textPos = nameTxt->getSize(); | |||
| 28634 | textPos.w = ENEMYBAR_FRAME_WIDTH - widthChange; | |||
| 28635 | textPos.y = baseBg->pos.y; | |||
| 28636 | textPos.h = baseBg->pos.h; | |||
| 28637 | nameTxt->setSize(textPos); | |||
| 28638 | } | |||
| 28639 | ||||
| 28640 | int startY = hudFrame->getSize().h - ENEMYBAR_FRAME_START_Y - 100; | |||
| 28641 | if ( doFadeout ) | |||
| 28642 | { | |||
| 28643 | pos.y = startY + (15 * (100.0 - enemyBar->fadeOut) / 100.0); // slide out downwards | |||
| 28644 | } | |||
| 28645 | else | |||
| 28646 | { | |||
| 28647 | pos.y = startY; | |||
| 28648 | } | |||
| 28649 | whichFrame->setSize(pos); | |||
| 28650 | ||||
| 28651 | //messagePlayer(0, "%.2f | %.2f | %.2f | %d", enemyDetails->animateValue, | |||
| 28652 | // enemyDetails->animateValue2, enemyDetails->animatePreviousSetpoint, enemyDetails->animateSetpoint); | |||
| 28653 | ||||
| 28654 | enemyBar->animatePreviousSetpoint = enemyBar->animateSetpoint; | |||
| 28655 | real_t& hpForegroundValue = enemyBar->animateValue; | |||
| 28656 | real_t& hpFadedValue = enemyBar->animateValue2; | |||
| 28657 | ||||
| 28658 | if ( enemyDetails ) | |||
| 28659 | { | |||
| 28660 | enemyBar->animateSetpoint = enemyDetails->enemy_hp; | |||
| 28661 | if ( enemyBar->animateSetpoint < enemyBar->animatePreviousSetpoint ) // insta-change as losing health | |||
| 28662 | { | |||
| 28663 | hpForegroundValue = enemyBar->animateSetpoint; | |||
| 28664 | enemyBar->animateTicks = ticks; | |||
| 28665 | } | |||
| 28666 | ||||
| 28667 | if ( enemyBar->maxValue > enemyDetails->enemy_maxhp ) | |||
| 28668 | { | |||
| 28669 | hpFadedValue = enemyBar->animateSetpoint; // resetting game etc, stop fade animation sticking out of frame | |||
| 28670 | } | |||
| 28671 | enemyBar->maxValue = enemyDetails->enemy_maxhp; | |||
| 28672 | } | |||
| 28673 | ||||
| 28674 | ||||
| 28675 | if ( hpForegroundValue < enemyBar->animateSetpoint ) // gaining HP, animate | |||
| 28676 | { | |||
| 28677 | real_t setpointDiff = std::max(0.01, enemyBar->animateSetpoint - hpForegroundValue); | |||
| 28678 | real_t fpsScale = getFPSScale(144.0); | |||
| 28679 | hpForegroundValue += fpsScale * (setpointDiff / 20.0); // reach it in 20 intervals, scaled to FPS | |||
| 28680 | hpForegroundValue = std::min(static_cast<real_t>(enemyBar->animateSetpoint), hpForegroundValue); | |||
| 28681 | ||||
| 28682 | if ( abs(enemyBar->animateSetpoint) - abs(hpForegroundValue) <= .05 ) | |||
| 28683 | { | |||
| 28684 | hpForegroundValue = enemyBar->animateSetpoint; | |||
| 28685 | } | |||
| 28686 | } | |||
| 28687 | else if ( hpForegroundValue > enemyBar->animateSetpoint ) // losing HP, snap to value | |||
| 28688 | { | |||
| 28689 | hpForegroundValue = enemyBar->animateSetpoint; | |||
| 28690 | } | |||
| 28691 | ||||
| 28692 | if ( hpFadedValue < enemyBar->animateSetpoint ) | |||
| 28693 | { | |||
| 28694 | hpFadedValue = hpForegroundValue; | |||
| 28695 | enemyBar->animateTicks = ticks; | |||
| 28696 | } | |||
| 28697 | else if ( hpFadedValue > enemyBar->animateSetpoint ) | |||
| 28698 | { | |||
| 28699 | if ( ticks - enemyBar->animateTicks > 30 || enemyBar->animateSetpoint <= 0 ) // fall after x ticks | |||
| 28700 | { | |||
| 28701 | real_t setpointDiff = std::max(0.01, hpFadedValue - enemyBar->animateSetpoint); | |||
| 28702 | real_t fpsScale = getFPSScale(144.0); | |||
| 28703 | real_t intervals = 10.0; | |||
| 28704 | if ( enemyBar->animateSetpoint <= 0 ) | |||
| 28705 | { | |||
| 28706 | intervals = 30.0; // dramatic | |||
| 28707 | } | |||
| 28708 | hpFadedValue -= fpsScale * (setpointDiff / intervals); // reach it in X intervals, scaled to FPS | |||
| 28709 | hpFadedValue = std::max(static_cast<real_t>(enemyBar->animateSetpoint), hpFadedValue); | |||
| 28710 | } | |||
| 28711 | } | |||
| 28712 | else | |||
| 28713 | { | |||
| 28714 | enemyBar->animateTicks = ticks; | |||
| 28715 | } | |||
| 28716 | ||||
| 28717 | auto skullFrame = whichFrame->findFrame("skull frame"); | |||
| 28718 | std::vector<std::pair<Frame::image_t*, int>> allSkulls; | |||
| 28719 | allSkulls.push_back(std::make_pair(skullFrame->findImage("skull 0 img"), 0)); | |||
| 28720 | allSkulls.push_back(std::make_pair(skullFrame->findImage("skull 25 img"), 25)); | |||
| 28721 | allSkulls.push_back(std::make_pair(skullFrame->findImage("skull 50 img"), 50)); | |||
| 28722 | allSkulls.push_back(std::make_pair(skullFrame->findImage("skull 100 img"), 75)); | |||
| 28723 | real_t healthPercentage = 100 * enemyBar->animateSetpoint / std::max(1.0, enemyBar->maxValue); | |||
| 28724 | for ( auto& skull : allSkulls ) | |||
| 28725 | { | |||
| 28726 | if ( !skull.first ) { continue; } | |||
| 28727 | ||||
| 28728 | Uint8 r, g, b, a; | |||
| 28729 | getColor(skull.first->color, &r, &g, &b, &a); | |||
| 28730 | ||||
| 28731 | if ( (int)healthPercentage < skull.second ) | |||
| 28732 | { | |||
| 28733 | real_t opacityChange = 4 * getFPSScale(60.0); // change independent of fps | |||
| 28734 | a = std::max(0, a - (int)opacityChange); | |||
| 28735 | } | |||
| 28736 | else if ( (int)healthPercentage >= skull.second ) | |||
| 28737 | { | |||
| 28738 | real_t opacityChange = 255;// *getFPSScale(144.0); // change independent of fps | |||
| 28739 | a = std::min(255, a + (int)opacityChange); | |||
| 28740 | } | |||
| 28741 | a *= whichFrame->getOpacity() / 100.0; | |||
| 28742 | skull.first->color = makeColor( r, g, b, a); | |||
| 28743 | } | |||
| 28744 | ||||
| 28745 | //char playerHPText[16]; | |||
| 28746 | //snprintf(playerHPText, sizeof(playerHPText), "%d", stats[player.playernum]->HP); | |||
| 28747 | if ( enemyDetails ) | |||
| 28748 | { | |||
| 28749 | nameTxt->setText(enemyDetails->enemy_name.c_str()); | |||
| 28750 | } | |||
| 28751 | ||||
| 28752 | //auto hpText = hpForegroundFrame->findField("hp text"); | |||
| 28753 | //hpText->setText(playerHPText); | |||
| 28754 | ||||
| 28755 | real_t foregroundPercent = hpForegroundValue / enemyBar->maxValue; | |||
| 28756 | hpProgress->pos.w = std::max(1, static_cast<int>((progressWidth) * foregroundPercent)); | |||
| 28757 | hpProgressEndcap->pos.x = hpProgress->pos.x + hpProgress->pos.w; | |||
| 28758 | ||||
| 28759 | real_t fadePercent = hpFadedValue / enemyBar->maxValue; | |||
| 28760 | dmgProgress->pos.w = std::max(1, static_cast<int>((progressWidth) * fadePercent)); | |||
| 28761 | dmgEndCap->pos.x = dmgProgress->pos.x + dmgProgress->pos.w; | |||
| 28762 | if ( dmgProgress->pos.w == 1 && enemyBar->animateSetpoint <= 0 ) | |||
| 28763 | { | |||
| 28764 | dmgProgress->disabled = true; | |||
| 28765 | real_t opacity = dmgFrame->getOpacity(); | |||
| 28766 | real_t opacityChange = .5 * getFPSScale(144.0); // change by .05% independent of fps | |||
| 28767 | dmgFrame->setOpacity(std::max(0.0, opacity - opacityChange)); | |||
| 28768 | dmgFrame->setOpacity(dmgFrame->getOpacity() * whichFrame->getOpacity() / 100.0); | |||
| 28769 | // make this element fade out to the left | |||
| 28770 | dmgEndCap->pos.x = 0 - (dmgEndCap->pos.w * (1.0 - opacity / 100.0)); | |||
| 28771 | } | |||
| 28772 | else | |||
| 28773 | { | |||
| 28774 | dmgProgress->disabled = false; | |||
| 28775 | dmgFrame->setOpacity(whichFrame->getOpacity()); | |||
| 28776 | } | |||
| 28777 | ||||
| 28778 | //bubblesImg->pos.x = dmgEndCap->pos.x - bubblesImg->pos.w; | |||
| 28779 | ||||
| 28780 | if ( enemyBar->animateSetpoint <= 0 ) | |||
| 28781 | { | |||
| 28782 | // hide all the progress elements when dead, as endcap/base don't shrink | |||
| 28783 | // hpProgress width 0px defaults to original size, so hide that too | |||
| 28784 | hpProgress->disabled = true; | |||
| 28785 | hpProgressEndcap->disabled = true; | |||
| 28786 | } | |||
| 28787 | else | |||
| 28788 | { | |||
| 28789 | hpProgress->disabled = false; | |||
| 28790 | hpProgressEndcap->disabled = false; | |||
| 28791 | } | |||
| 28792 | ||||
| 28793 | auto dmgText = hudFrame->findField("enemy dmg txt"); | |||
| 28794 | // damage number on HUD | |||
| 28795 | { | |||
| 28796 | if ( damageNumber >= 0 ) | |||
| 28797 | { | |||
| 28798 | char buf[128] = ""; | |||
| 28799 | snprintf(buf, sizeof(buf), "%d", damageNumber); | |||
| 28800 | dmgText->setText(buf); | |||
| 28801 | dmgText->setDisabled(false); | |||
| 28802 | SDL_Rect txtPos = dmgText->getSize(); | |||
| 28803 | SDL_Rect barPos = foregroundFrame->getAbsoluteSize(); | |||
| 28804 | //txtPos.x = barPos.x + baseBg->pos.x/* + baseBg->pos.w*/; | |||
| 28805 | //txtPos.y = barPos.y - 30; | |||
| 28806 | auto text = Text::get(dmgText->getText(), dmgText->getFont(), | |||
| 28807 | makeColor(255, 255, 255, 255), makeColor(0, 0, 0, 255)); | |||
| 28808 | txtPos.x = 30 + player.camera_virtualWidth() / 2; | |||
| 28809 | txtPos.y = -50 + player.camera_virtualHeight() / 2; | |||
| 28810 | txtPos.w = text->getWidth(); | |||
| 28811 | txtPos.h = text->getHeight(); | |||
| 28812 | dmgText->setSize(txtPos); | |||
| 28813 | hudDamageTextVelocityX = 1.0; | |||
| 28814 | hudDamageTextVelocityY = 3.0; | |||
| 28815 | Uint8 r, g, b, a; | |||
| 28816 | getColor(dmgText->getColor(), &r, &g, &b, &a); | |||
| 28817 | dmgText->setColor(makeColor(r, g, b, 255)); | |||
| 28818 | } | |||
| 28819 | ||||
| 28820 | if ( !dmgText->isDisabled() ) | |||
| 28821 | { | |||
| 28822 | SDL_Rect txtPos = dmgText->getSize(); | |||
| 28823 | txtPos.x += hudDamageTextVelocityX; | |||
| 28824 | txtPos.y -= hudDamageTextVelocityY; | |||
| 28825 | hudDamageTextVelocityX += .05; | |||
| 28826 | hudDamageTextVelocityY -= .3; | |||
| 28827 | dmgText->setSize(txtPos); | |||
| 28828 | if ( hudDamageTextVelocityY < -2.0 ) | |||
| 28829 | { | |||
| 28830 | Uint8 r, g, b, a; | |||
| 28831 | getColor(dmgText->getColor(), &r, &g, &b, &a); | |||
| 28832 | a = (std::max(0, (int)a - 16)); | |||
| 28833 | dmgText->setColor(makeColor(r, g, b, a)); | |||
| 28834 | if ( a == 0 ) | |||
| 28835 | { | |||
| 28836 | dmgText->setDisabled(true); | |||
| 28837 | } | |||
| 28838 | } | |||
| 28839 | } | |||
| 28840 | } | |||
| 28841 | ||||
| 28842 | if ( enemyDetails ) | |||
| 28843 | { | |||
| 28844 | enemyDetails->animator.previousSetpoint = enemyBar->animatePreviousSetpoint; | |||
| 28845 | enemyDetails->animator.foregroundValue = enemyBar->animateValue; | |||
| 28846 | enemyDetails->animator.backgroundValue = enemyBar->animateValue2; | |||
| 28847 | enemyDetails->animator.setpoint = enemyBar->animateSetpoint; | |||
| 28848 | enemyDetails->animator.animateTicks = enemyBar->animateTicks; | |||
| 28849 | enemyDetails->animator.maxValue = enemyBar->maxValue; | |||
| 28850 | enemyDetails->animator.fadeIn = enemyBar->fadeIn; | |||
| 28851 | enemyDetails->animator.fadeOut = enemyBar->fadeOut; | |||
| 28852 | if ( enemyDetails->worldTexture ) | |||
| 28853 | { | |||
| 28854 | delete enemyDetails->worldTexture; | |||
| 28855 | enemyDetails->worldTexture = nullptr; | |||
| 28856 | } | |||
| 28857 | if ( enemyDetails->worldSurfaceSprite ) | |||
| 28858 | { | |||
| 28859 | SDL_FreeSurface(enemyDetails->worldSurfaceSprite); | |||
| 28860 | enemyDetails->worldSurfaceSprite = nullptr; | |||
| 28861 | } | |||
| 28862 | enemyDetails->worldSurfaceSprite = enemyDetails->blitEnemyBar(player.playernum, enemyDetails->worldSurfaceSpriteStatusEffects); | |||
| 28863 | enemyDetails->worldTexture = new TempTexture(); | |||
| 28864 | enemyDetails->worldTexture->load(enemyDetails->worldSurfaceSprite, false, true); | |||
| 28865 | } | |||
| 28866 | ||||
| 28867 | whichFrame->setDisabled(true); | |||
| 28868 | } | |||
| 28869 | ||||
| 28870 | const int HPMPdividerThresholdInterval = 20; | |||
| 28871 | const int kHPMPWidthReduce2pWideClippedActionPrompts = 60; | |||
| 28872 | //static ConsoleVariable<int> cvar_hpanimdebug("/hpmpanimdebug", 1); | |||
| 28873 | void Player::HUD_t::updateHPBar() | |||
| 28874 | { | |||
| 28875 | if ( !hpFrame ) | |||
| 28876 | { | |||
| 28877 | return; | |||
| 28878 | } | |||
| 28879 | ||||
| 28880 | bool bCompactWidth = false; | |||
| 28881 | bool bCompactHeight = player.bUseCompactGUIHeight(); | |||
| 28882 | if ( player.bUseCompactGUIWidth() || (keystatus[SDLK_t] && enableDebugKeys) ) | |||
| 28883 | { | |||
| 28884 | bCompactWidth = true; | |||
| 28885 | } | |||
| 28886 | ||||
| 28887 | SDL_Rect pos = hpFrame->getSize(); | |||
| 28888 | pos.w = HPMP_FRAME_WIDTH + (bCompactWidth ? hpmpbarCompactOffsetWidth : hpmpbarOffsetWidth); | |||
| 28889 | if ( !player.bUseCompactGUIWidth() | |||
| 28890 | && player.bUseCompactGUIHeight() && *MainMenu::clipped_splitscreen | |||
| 28891 | && bShortHPMPForActionBars ) | |||
| 28892 | { | |||
| 28893 | // shorten if action prompts visible in clipped wide mode | |||
| 28894 | pos.w -= kHPMPWidthReduce2pWideClippedActionPrompts; | |||
| 28895 | } | |||
| 28896 | pos.x = HPMP_FRAME_START_X + ((bCompactWidth || bCompactHeight) ? hpmpbarCompactOffsetX : hpmpbarOffsetX); | |||
| 28897 | pos.y = hudFrame->getSize().h - HPMP_FRAME_START_Y + ((bCompactWidth || bCompactHeight) ? hpmpbarCompactOffsetY : hpmpbarOffsetY); | |||
| 28898 | pos.y -= player.hud.offsetHUDAboveHotbarHeight; | |||
| 28899 | hpFrame->setSize(pos); | |||
| 28900 | ||||
| 28901 | auto hpForegroundFrame = hpFrame->findFrame("hp foreground frame"); | |||
| 28902 | { | |||
| 28903 | auto _pos = hpForegroundFrame->getSize(); | |||
| 28904 | _pos.w = pos.w; | |||
| 28905 | hpForegroundFrame->setSize(_pos); | |||
| 28906 | } | |||
| 28907 | auto hpBg = hpFrame->findImage("hp img base"); | |||
| 28908 | auto hpEndcap = hpForegroundFrame->findImage("hp img endcap"); | |||
| 28909 | auto hpProgressBot = hpForegroundFrame->findImage("hp img progress bot"); | |||
| 28910 | auto hpProgress = hpForegroundFrame->findImage("hp img progress"); | |||
| 28911 | auto hpProgressEndCap = hpForegroundFrame->findImage("hp img progress endcap"); | |||
| 28912 | auto hpFadeFrame = hpFrame->findFrame("hp fade frame"); | |||
| 28913 | { | |||
| 28914 | auto _pos = hpFadeFrame->getSize(); | |||
| 28915 | _pos.w = pos.w; | |||
| 28916 | hpFadeFrame->setSize(_pos); | |||
| 28917 | } | |||
| 28918 | auto hpFadedBase = hpFadeFrame->findImage("hp img fade bot"); | |||
| 28919 | auto hpFaded = hpFadeFrame->findImage("hp img fade"); | |||
| 28920 | auto hpFadedEndCap = hpFadeFrame->findImage("hp img fade endcap"); | |||
| 28921 | ||||
| 28922 | real_t progressWidth = hpFrame->getSize().w - 74; | |||
| 28923 | int backgroundWidth = hpFrame->getSize().w - 54; | |||
| 28924 | ||||
| 28925 | // handle bar size changing | |||
| 28926 | { | |||
| 28927 | real_t multiplier = 1.0; | |||
| 28928 | const Sint32 maxHPWidth = (bCompactWidth ? hpmpbarCompactMaxWidthAmount : hpmpbarMaxWidthAmount); | |||
| 28929 | if ( stats[player.playernum]->MAXHP < maxHPWidth ) | |||
| 28930 | { | |||
| 28931 | // start at 30%, increase 2.5% every 5 HP past 20 MAXHP | |||
| 28932 | multiplier = (bCompactWidth ? hpmpbarCompactBasePercentSize : hpmpbarBasePercentSize) / 100.0; | |||
| 28933 | real_t widthIntervalPercent = (bCompactWidth ? hpmpbarCompactWidthIncreasePercentOnInterval : hpmpbarWidthIncreasePercentOnInterval) / 100.0; | |||
| 28934 | int intervalThreshold = (bCompactWidth ? hpmpbarCompactIntervalToIncreaseWidth : hpmpbarIntervalToIncreaseWidth); | |||
| 28935 | int baseIntervalStart = (bCompactWidth ? hpmpbarCompactIntervalStartValue : hpmpbarIntervalStartValue); | |||
| 28936 | multiplier += (widthIntervalPercent * ((std::max(0, stats[player.playernum]->MAXHP - baseIntervalStart) / intervalThreshold))); | |||
| 28937 | } | |||
| 28938 | ||||
| 28939 | int diff = static_cast<int>(std::max(0.0, progressWidth - progressWidth * multiplier)); // how many pixels the progress bar shrinks | |||
| 28940 | progressWidth *= multiplier; // scale the progress bars | |||
| 28941 | hpBg->pos.w = backgroundWidth - diff; // move the background bar by x pixels as above | |||
| 28942 | hpEndcap->pos.x = hpFrame->getSize().w - hpEndcap->pos.w - diff; // move the background endcap by x pixels as above | |||
| 28943 | } | |||
| 28944 | ||||
| 28945 | HPBar.animatePreviousSetpoint = HPBar.animateSetpoint; | |||
| 28946 | real_t& hpForegroundValue = HPBar.animateValue; | |||
| 28947 | real_t& hpFadedValue = HPBar.animateValue2; | |||
| 28948 | ||||
| 28949 | HPBar.animateSetpoint = stats[player.playernum]->HP; | |||
| 28950 | if ( HPBar.animateSetpoint < HPBar.animatePreviousSetpoint ) // insta-change as losing health | |||
| 28951 | { | |||
| 28952 | hpForegroundValue = HPBar.animateSetpoint; | |||
| 28953 | HPBar.animateTicks = ticks; | |||
| 28954 | ||||
| 28955 | // flash for taking damage | |||
| 28956 | HPBar.flashTicks = ticks; | |||
| 28957 | HPBar.flashAnimState = -1; | |||
| 28958 | HPBar.flashType = FLASH_ON_DAMAGE; | |||
| 28959 | } | |||
| 28960 | ||||
| 28961 | if ( HPBar.maxValue > stats[player.playernum]->MAXHP ) | |||
| 28962 | { | |||
| 28963 | hpFadedValue = HPBar.animateSetpoint; // resetting game etc, stop fade animation sticking out of frame | |||
| 28964 | } | |||
| 28965 | ||||
| 28966 | HPBar.maxValue = stats[player.playernum]->MAXHP; | |||
| 28967 | ||||
| 28968 | if ( hpForegroundValue < HPBar.animateSetpoint ) // gaining HP, animate | |||
| 28969 | { | |||
| 28970 | // flash for gaining HP, provided not already flashing | |||
| 28971 | /*if ( HPBar.flashAnimState == -1 || (HPBar.flashAnimState >= 0 && HPBar.flashType != FLASH_ON_DAMAGE) ) | |||
| 28972 | { | |||
| 28973 | HPBar.flashTicks = ticks; | |||
| 28974 | HPBar.flashAnimState = -1; | |||
| 28975 | HPBar.flashType = FLASH_ON_RECOVERY; | |||
| 28976 | }*/ | |||
| 28977 | ||||
| 28978 | real_t setpointDiff = std::max(0.0, HPBar.animateSetpoint - hpForegroundValue); | |||
| 28979 | real_t fpsScale = getFPSScale(144.0); | |||
| 28980 | hpForegroundValue += fpsScale * (setpointDiff / 20.0); // reach it in 20 intervals, scaled to FPS | |||
| 28981 | hpForegroundValue = std::min(static_cast<real_t>(HPBar.animateSetpoint), hpForegroundValue); | |||
| 28982 | ||||
| 28983 | if ( abs(HPBar.animateSetpoint) - abs(hpForegroundValue) <= 1.0 ) | |||
| 28984 | { | |||
| 28985 | hpForegroundValue = HPBar.animateSetpoint; | |||
| 28986 | } | |||
| 28987 | ||||
| 28988 | /* int increment = 3; | |||
| 28989 | double scaledIncrement = (increment * (getFPSScale(144.0)));*/ | |||
| 28990 | //real_t diff = std::max(.1, (HPBar.animateSetpoint * 10 - hpForegroundValue) / (maxValue / 5)); // 0.1-5 value | |||
| 28991 | //if ( HPBar.animateSetpoint * 10 >= maxValue ) | |||
| 28992 | //{ | |||
| 28993 | // diff = 5; | |||
| 28994 | //} | |||
| 28995 | //scaledIncrement *= 0.2 * pow(diff, 2) + .5; | |||
| 28996 | ||||
| 28997 | //hpForegroundValue = std::min(HPBar.animateSetpoint * 10.0, hpForegroundValue + scaledIncrement); | |||
| 28998 | //messagePlayer(0, "%.2f | %.2f", hpForegroundValue); | |||
| 28999 | } | |||
| 29000 | else if ( hpForegroundValue > HPBar.animateSetpoint ) // losing HP, snap to value | |||
| 29001 | { | |||
| 29002 | hpForegroundValue = HPBar.animateSetpoint; | |||
| 29003 | } | |||
| 29004 | ||||
| 29005 | if ( hpFadedValue < HPBar.animateSetpoint ) | |||
| 29006 | { | |||
| 29007 | hpFadedValue = hpForegroundValue; | |||
| 29008 | HPBar.animateTicks = ticks; | |||
| 29009 | } | |||
| 29010 | else if ( hpFadedValue > HPBar.animateSetpoint ) | |||
| 29011 | { | |||
| 29012 | if ( ticks - HPBar.animateTicks > 30 /*|| stats[player.playernum]->HP <= 0*/ ) // fall after x ticks | |||
| 29013 | { | |||
| 29014 | real_t setpointDiff = std::max(0.01, hpFadedValue - HPBar.animateSetpoint); | |||
| 29015 | real_t fpsScale = getFPSScale(144.0); | |||
| 29016 | hpFadedValue -= fpsScale * (setpointDiff / 20.0); // reach it in 20 intervals, scaled to FPS | |||
| 29017 | hpFadedValue = std::max(static_cast<real_t>(HPBar.animateSetpoint), hpFadedValue); | |||
| 29018 | } | |||
| 29019 | } | |||
| 29020 | else | |||
| 29021 | { | |||
| 29022 | HPBar.animateTicks = ticks; | |||
| 29023 | } | |||
| 29024 | ||||
| 29025 | char playerHPText[16]; | |||
| 29026 | snprintf(playerHPText, sizeof(playerHPText), "%d", stats[player.playernum]->HP); | |||
| 29027 | ||||
| 29028 | auto hpText = hpForegroundFrame->findField("hp text"); | |||
| 29029 | hpText->setText(playerHPText); | |||
| 29030 | ||||
| 29031 | real_t foregroundPercent = hpForegroundValue / HPBar.maxValue; | |||
| 29032 | hpProgress->pos.w = std::max(1, static_cast<int>((progressWidth) * foregroundPercent)); | |||
| 29033 | hpProgressEndCap->pos.x = hpProgress->pos.x + hpProgress->pos.w; | |||
| 29034 | ||||
| 29035 | real_t fadePercent = hpFadedValue / HPBar.maxValue; | |||
| 29036 | hpFaded->pos.w = std::max(1, static_cast<int>((progressWidth) * fadePercent)); | |||
| 29037 | hpFadedEndCap->pos.x = hpFaded->pos.x + hpFaded->pos.w; | |||
| 29038 | if ( hpFaded->pos.w == 1 && stats[player.playernum]->HP <= 0 ) | |||
| 29039 | { | |||
| 29040 | hpFaded->disabled = true; | |||
| 29041 | real_t opacity = hpFadeFrame->getOpacity(); | |||
| 29042 | real_t opacityChange = .5 * getFPSScale(144.0); // change by .05% independant of fps | |||
| 29043 | hpFadeFrame->setOpacity(std::max(0.0, opacity - opacityChange)); | |||
| 29044 | ||||
| 29045 | // make this element fade out to the left, starting 54px then finally at 40px. @ 40px it's out of shot (6 width + 8 endcap width) | |||
| 29046 | hpFadedBase->pos.x = 54 - (14 * (1.0 - opacity / 100.0)); | |||
| 29047 | hpFadedEndCap->pos.x = hpFadedBase->pos.x + hpFadedBase->pos.w; | |||
| 29048 | } | |||
| 29049 | else | |||
| 29050 | { | |||
| 29051 | hpFaded->disabled = false; | |||
| 29052 | hpFadeFrame->setOpacity(100.0); | |||
| 29053 | ||||
| 29054 | // reset to 54px left as we altered in above if statement | |||
| 29055 | hpFadedBase->pos.x = 54; | |||
| 29056 | } | |||
| 29057 | ||||
| 29058 | if ( stats[player.playernum]->HP <= 0 ) | |||
| 29059 | { | |||
| 29060 | // hide all the progress elements when dead, as endcap/base don't shrink | |||
| 29061 | // hpProgress width 0px defaults to original size, so hide that too | |||
| 29062 | hpProgress->disabled = true; | |||
| 29063 | hpProgressEndCap->disabled = true; | |||
| 29064 | hpProgressBot->disabled = true; | |||
| 29065 | } | |||
| 29066 | else | |||
| 29067 | { | |||
| 29068 | hpProgress->disabled = false; | |||
| 29069 | hpProgressEndCap->disabled = false; | |||
| 29070 | hpProgressBot->disabled = false; | |||
| 29071 | } | |||
| 29072 | ||||
| 29073 | // dividers | |||
| 29074 | { | |||
| 29075 | const int fullBarWidth = hpProgressBot->pos.w + progressWidth + hpEndcap->pos.w / 2; | |||
| 29076 | auto div25Percent = hpForegroundFrame->findImage("hp img div 25pc"); | |||
| 29077 | div25Percent->disabled = false; | |||
| 29078 | div25Percent->pos.x = hpProgressBot->pos.x + fullBarWidth * .25 - 2; | |||
| 29079 | auto div50Percent = hpForegroundFrame->findImage("hp img div 50pc"); | |||
| 29080 | div50Percent->disabled = false; | |||
| 29081 | div50Percent->pos.x = hpProgressBot->pos.x + fullBarWidth * .5 - 2; | |||
| 29082 | auto div75Percent = hpForegroundFrame->findImage("hp img div 75pc"); | |||
| 29083 | div75Percent->disabled = false; | |||
| 29084 | div75Percent->pos.x = hpProgressBot->pos.x + fullBarWidth * .75 - 2; | |||
| 29085 | ||||
| 29086 | if ( div50Percent->pos.x - div25Percent->pos.x < HPMPdividerThresholdInterval ) | |||
| 29087 | { | |||
| 29088 | div75Percent->disabled = true; | |||
| 29089 | // 2 dividers 33%/66% | |||
| 29090 | div25Percent->pos.x = hpProgressBot->pos.x + fullBarWidth * .33 - 2; | |||
| 29091 | div50Percent->pos.x = hpProgressBot->pos.x + fullBarWidth * .66 - 2; | |||
| 29092 | if ( div50Percent->pos.x - div25Percent->pos.x < HPMPdividerThresholdInterval ) | |||
| 29093 | { | |||
| 29094 | // 1 divider 50% | |||
| 29095 | div25Percent->disabled = true; | |||
| 29096 | div50Percent->pos.x = hpProgressBot->pos.x + fullBarWidth * .5 - 2; | |||
| 29097 | } | |||
| 29098 | } | |||
| 29099 | } | |||
| 29100 | ||||
| 29101 | hpProgress->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPMid_00.png"; | |||
| 29102 | hpProgressBot->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPBot_00.png"; | |||
| 29103 | hpProgressEndCap->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPEnd_00.png"; | |||
| 29104 | auto hpProgressEndCapFlash = hpForegroundFrame->findImage("hp img progress endcap flash"); | |||
| 29105 | hpProgressEndCapFlash->disabled = true; | |||
| 29106 | const int framesPerAnimation = (HPBar.flashType == FLASH_ON_DAMAGE ? 1 : 2)/* * *cvar_hpanimdebug*/; | |||
| 29107 | const int numAnimationFrames = (HPBar.flashType == FLASH_ON_DAMAGE ? 20 : 2)/* * *cvar_hpanimdebug*/; | |||
| 29108 | if ( HPBar.flashTicks > 0 ) | |||
| 29109 | { | |||
| 29110 | //messagePlayer(0, MESSAGE_DEBUG, "ticks: %d, animticks: %d, state: %d", ticks, HPBarFlashTicks, HPBarFlashAnimState); | |||
| 29111 | if ( HPBar.flashAnimState > numAnimationFrames || hpProgress->disabled ) | |||
| 29112 | { | |||
| 29113 | HPBar.flashTicks = 0; | |||
| 29114 | HPBar.flashType = FLASH_ON_DAMAGE; | |||
| 29115 | HPBar.flashAnimState = -1; | |||
| 29116 | hpProgressEndCapFlash->disabled = true; | |||
| 29117 | } | |||
| 29118 | else | |||
| 29119 | { | |||
| 29120 | hpProgressEndCapFlash->disabled = hpProgressEndCap->disabled; | |||
| 29121 | if ( ticks == HPBar.flashTicks ) | |||
| 29122 | { | |||
| 29123 | HPBar.flashAnimState = 1; | |||
| 29124 | HPBar.flashProcessedOnTick = ticks; | |||
| 29125 | } | |||
| 29126 | else if ( (HPBar.flashProcessedOnTick != ticks) | |||
| 29127 | && (ticks > HPBar.flashTicks) | |||
| 29128 | && (ticks - HPBar.flashTicks) % framesPerAnimation == 0 ) | |||
| 29129 | { | |||
| 29130 | ++HPBar.flashAnimState; | |||
| 29131 | HPBar.flashProcessedOnTick = ticks; | |||
| 29132 | } | |||
| 29133 | ||||
| 29134 | if ( HPBar.flashType == 0 ) | |||
| 29135 | { | |||
| 29136 | if ( HPBar.flashAnimState <= 6 ) | |||
| 29137 | { | |||
| 29138 | hpProgressEndCapFlash->color = 0xFFFFFFFF; | |||
| 29139 | } | |||
| 29140 | ||||
| 29141 | if ( HPBar.flashAnimState == 0 ) | |||
| 29142 | { | |||
| 29143 | hpProgress->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPMid_00.png"; | |||
| 29144 | hpProgressEndCapFlash->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPEnd_F00.png"; | |||
| 29145 | hpProgressBot->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPBot_00.png"; | |||
| 29146 | } | |||
| 29147 | else if ( HPBar.flashAnimState >= 1 && HPBar.flashAnimState <= 2 ) | |||
| 29148 | { | |||
| 29149 | hpProgress->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPMid_01.png"; | |||
| 29150 | hpProgressEndCapFlash->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPEnd_F01.png"; | |||
| 29151 | hpProgressBot->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPBot_01.png"; | |||
| 29152 | } | |||
| 29153 | else if ( HPBar.flashAnimState == 3 ) | |||
| 29154 | { | |||
| 29155 | hpProgress->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPMid_02.png"; | |||
| 29156 | hpProgressEndCapFlash->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPEnd_F02.png"; | |||
| 29157 | hpProgressBot->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPBot_02.png"; | |||
| 29158 | } | |||
| 29159 | else if ( HPBar.flashAnimState >= 4 && HPBar.flashAnimState <= 5 ) | |||
| 29160 | { | |||
| 29161 | hpProgress->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPMid_01.png"; | |||
| 29162 | hpProgressEndCapFlash->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPEnd_F01.png"; | |||
| 29163 | hpProgressBot->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPBot_01.png"; | |||
| 29164 | } | |||
| 29165 | else if ( HPBar.flashAnimState == 6 ) | |||
| 29166 | { | |||
| 29167 | hpProgress->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPMid_03.png"; | |||
| 29168 | hpProgressEndCapFlash->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPEnd_F03.png"; | |||
| 29169 | hpProgressBot->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPBot_03.png"; | |||
| 29170 | } | |||
| 29171 | else | |||
| 29172 | { | |||
| 29173 | hpProgress->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPMid_00.png"; | |||
| 29174 | hpProgressEndCapFlash->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPEnd_F04.png"; | |||
| 29175 | Uint8 r, g, b, a; | |||
| 29176 | getColor(hpProgressEndCapFlash->color, &r, &g, &b, &a); | |||
| 29177 | int decrement = 20; | |||
| 29178 | real_t fpsScale = getFPSScale(60.0); | |||
| 29179 | decrement *= fpsScale; | |||
| 29180 | a = std::max(0, (int)a - decrement); | |||
| 29181 | hpProgressEndCapFlash->color = makeColor(r, g, b, a); | |||
| 29182 | } | |||
| 29183 | } | |||
| 29184 | else | |||
| 29185 | { | |||
| 29186 | hpProgressEndCapFlash->color = 0xFFFFFFFF; | |||
| 29187 | hpProgressEndCapFlash->disabled = true; | |||
| 29188 | if ( HPBar.flashAnimState == 1 ) | |||
| 29189 | { | |||
| 29190 | hpProgress->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPMid_03.png"; | |||
| 29191 | hpProgressBot->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPBot_03.png"; | |||
| 29192 | hpProgressEndCap->path = "*#images/ui/HUD/hpmpbars/HUD_Bars_HPEnd_01.png"; | |||
| 29193 | } | |||
| 29194 | } | |||
| 29195 | } | |||
| 29196 | } | |||
| 29197 | else | |||
| 29198 | { | |||
| 29199 | HPBar.flashAnimState = -1; | |||
| 29200 | hpProgressEndCapFlash->disabled = true; | |||
| 29201 | } | |||
| 29202 | { | |||
| 29203 | hpProgressEndCapFlash->pos.w = 22; | |||
| 29204 | hpProgressEndCapFlash->section.x = 0; | |||
| 29205 | hpProgressEndCapFlash->section.w = 0; | |||
| 29206 | if ( !hpProgressEndCap->disabled ) | |||
| 29207 | { | |||
| 29208 | hpProgressEndCapFlash->pos.x = hpProgressEndCap->pos.x - (hpProgressEndCapFlash->pos.w - hpProgressEndCap->pos.w); | |||
| 29209 | } | |||
| 29210 | if ( hpProgressEndCapFlash->pos.x < hpProgressBot->pos.x ) | |||
| 29211 | { | |||
| 29212 | // adjust end cap flash to clip correctly sliding past end of bar | |||
| 29213 | int overflowx = (hpProgressBot->pos.x - hpProgressEndCapFlash->pos.x); | |||
| 29214 | hpProgressEndCapFlash->section.x = (overflowx); | |||
| 29215 | hpProgressEndCapFlash->pos.x += overflowx; | |||
| 29216 | hpProgressEndCapFlash->pos.w -= overflowx; | |||
| 29217 | hpProgressEndCapFlash->section.w = hpProgressEndCapFlash->pos.w; | |||
| 29218 | } | |||
| 29219 | } | |||
| 29220 | ||||
| 29221 | hpFrame->setDisabled(player.ghost.isActive()); | |||
| 29222 | } | |||
| 29223 | ||||
| 29224 | void Player::HUD_t::updateMPBar() | |||
| 29225 | { | |||
| 29226 | if ( !mpFrame ) | |||
| 29227 | { | |||
| 29228 | return; | |||
| 29229 | } | |||
| 29230 | ||||
| 29231 | bool bCompactWidth = false; | |||
| 29232 | bool bCompactHeight = player.bUseCompactGUIHeight(); | |||
| 29233 | if ( player.bUseCompactGUIWidth() || (keystatus[SDLK_t] && enableDebugKeys) ) | |||
| 29234 | { | |||
| 29235 | bCompactWidth = true; | |||
| 29236 | } | |||
| 29237 | ||||
| 29238 | SDL_Rect pos = mpFrame->getSize(); | |||
| 29239 | pos.w = HPMP_FRAME_WIDTH + (bCompactWidth ? hpmpbarCompactOffsetWidth : hpmpbarOffsetWidth); | |||
| 29240 | if ( !player.bUseCompactGUIWidth() | |||
| 29241 | && player.bUseCompactGUIHeight() && *MainMenu::clipped_splitscreen | |||
| 29242 | && bShortHPMPForActionBars ) | |||
| 29243 | { | |||
| 29244 | // shorten if action prompts visible in clipped wide mode | |||
| 29245 | pos.w -= kHPMPWidthReduce2pWideClippedActionPrompts; | |||
| 29246 | } | |||
| 29247 | pos.x = HPMP_FRAME_START_X + ((bCompactWidth || bCompactHeight) ? hpmpbarCompactOffsetX : hpmpbarOffsetX); | |||
| 29248 | pos.y = hudFrame->getSize().h - HPMP_FRAME_START_Y + HPMP_FRAME_HEIGHT + ((bCompactWidth || bCompactHeight) ? hpmpbarCompactOffsetY : hpmpbarOffsetY); | |||
| 29249 | pos.y -= player.hud.offsetHUDAboveHotbarHeight; | |||
| 29250 | mpFrame->setSize(pos); | |||
| 29251 | ||||
| 29252 | auto mpForegroundFrame = mpFrame->findFrame("mp foreground frame"); | |||
| 29253 | { | |||
| 29254 | auto _pos = mpForegroundFrame->getSize(); | |||
| 29255 | _pos.w = pos.w; | |||
| 29256 | mpForegroundFrame->setSize(_pos); | |||
| 29257 | } | |||
| 29258 | ||||
| 29259 | auto mpBg = mpFrame->findImage("mp img base"); | |||
| 29260 | auto mpEndcap = mpForegroundFrame->findImage("mp img endcap"); | |||
| 29261 | auto mpProgressBot = mpForegroundFrame->findImage("mp img progress bot"); | |||
| 29262 | auto mpProgress = mpForegroundFrame->findImage("mp img progress"); | |||
| 29263 | auto mpProgressEndCap = mpForegroundFrame->findImage("mp img progress endcap"); | |||
| 29264 | auto mpFadeFrame = mpFrame->findFrame("mp fade frame"); | |||
| 29265 | { | |||
| 29266 | auto _pos = mpFadeFrame->getSize(); | |||
| 29267 | _pos.w = pos.w; | |||
| 29268 | mpFadeFrame->setSize(_pos); | |||
| 29269 | } | |||
| 29270 | auto mpFadedBase = mpFadeFrame->findImage("mp img fade bot"); | |||
| 29271 | mpFadedBase->path = MPBarPaths_t::get(player.playernum, "mp img fade bot"); | |||
| 29272 | auto mpFaded = mpFadeFrame->findImage("mp img fade"); | |||
| 29273 | mpFaded->path = MPBarPaths_t::get(player.playernum, "mp img fade"); | |||
| 29274 | auto mpFadedEndCap = mpFadeFrame->findImage("mp img fade endcap"); | |||
| 29275 | mpFadedEndCap->path = MPBarPaths_t::get(player.playernum, "mp img fade endcap"); | |||
| 29276 | auto mpBase = mpForegroundFrame->findImage("mp img value"); | |||
| 29277 | mpBase->path = MPBarPaths_t::get(player.playernum, "mp img value"); | |||
| 29278 | ||||
| 29279 | real_t progressWidth = mpFrame->getSize().w - 74; | |||
| 29280 | int backgroundWidth = mpFrame->getSize().w - 54; | |||
| 29281 | ||||
| 29282 | // handle bar size changing | |||
| 29283 | { | |||
| 29284 | real_t multiplier = 1.0; | |||
| 29285 | const Sint32 maxMPWidth = (bCompactWidth ? hpmpbarCompactMaxWidthAmount : hpmpbarMaxWidthAmount); | |||
| 29286 | if ( stats[player.playernum]->MAXMP < maxMPWidth ) | |||
| 29287 | { | |||
| 29288 | // start at 30%, increase 2.5% every 5 MP past 20 MAXMP | |||
| 29289 | multiplier = (bCompactWidth ? hpmpbarCompactBasePercentSize : hpmpbarBasePercentSize) / 100.0; | |||
| 29290 | real_t widthIntervalPercent = (bCompactWidth ? hpmpbarCompactWidthIncreasePercentOnInterval : hpmpbarWidthIncreasePercentOnInterval) / 100.0; | |||
| 29291 | int intervalThreshold = (bCompactWidth ? hpmpbarCompactIntervalToIncreaseWidth : hpmpbarIntervalToIncreaseWidth); | |||
| 29292 | int baseIntervalStart = (bCompactWidth ? hpmpbarCompactIntervalStartValue : hpmpbarIntervalStartValue); | |||
| 29293 | multiplier += (widthIntervalPercent * ((std::max(0, stats[player.playernum]->MAXMP - baseIntervalStart) / intervalThreshold))); | |||
| 29294 | } | |||
| 29295 | ||||
| 29296 | int diff = static_cast<int>(std::max(0.0, progressWidth - progressWidth * multiplier)); // how many pixels the progress bar shrinks | |||
| 29297 | progressWidth *= multiplier; // scale the progress bars | |||
| 29298 | mpBg->pos.w = backgroundWidth - diff; // move the background bar by x pixels as above | |||
| 29299 | mpEndcap->pos.x = mpFrame->getSize().w - mpEndcap->pos.w - diff; // move the background endcap by x pixels as above | |||
| 29300 | } | |||
| 29301 | ||||
| 29302 | MPBar.animatePreviousSetpoint = MPBar.animateSetpoint; | |||
| 29303 | real_t& mpForegroundValue = MPBar.animateValue; | |||
| 29304 | real_t& mpFadedValue = MPBar.animateValue2; | |||
| 29305 | ||||
| 29306 | MPBar.animateSetpoint = stats[player.playernum]->MP; | |||
| 29307 | ||||
| 29308 | bool flashAnimationPreviouslyPlaying = MPBar.flashTicks > 0; | |||
| 29309 | if ( MPBar.animateSetpoint < MPBar.animatePreviousSetpoint ) // insta-change as losing health | |||
| 29310 | { | |||
| 29311 | mpForegroundValue = MPBar.animateSetpoint; | |||
| 29312 | MPBar.animateTicks = ticks; | |||
| 29313 | ||||
| 29314 | // flash for taking damage | |||
| 29315 | MPBar.flashTicks = ticks; | |||
| 29316 | MPBar.flashProcessedOnTick = 0; | |||
| 29317 | MPBar.flashAnimState = -1; | |||
| 29318 | MPBar.flashType = FLASH_ON_DAMAGE; | |||
| 29319 | } | |||
| 29320 | ||||
| 29321 | if ( MPBar.maxValue > stats[player.playernum]->MAXMP ) | |||
| 29322 | { | |||
| 29323 | mpFadedValue = MPBar.animateSetpoint; // resetting game etc, stop fade animation sticking out of frame | |||
| 29324 | } | |||
| 29325 | ||||
| 29326 | MPBar.maxValue = stats[player.playernum]->MAXMP; | |||
| 29327 | if ( mpForegroundValue < MPBar.animateSetpoint ) // gaining MP, animate | |||
| 29328 | { | |||
| 29329 | // flash for gaining MP, provided not already flashing | |||
| 29330 | /*if ( MPBar.flashAnimState == -1 || (MPBar.flashAnimState >= 0 && MPBar.flashType != FLASH_ON_DAMAGE) ) | |||
| 29331 | { | |||
| 29332 | MPBar.flashTicks = ticks; | |||
| 29333 | MPBar.flashAnimState = -1; | |||
| 29334 | MPBar.flashType = FLASH_ON_RECOVERY; | |||
| 29335 | }*/ | |||
| 29336 | ||||
| 29337 | real_t setpointDiff = std::max(.1, MPBar.animateSetpoint - mpForegroundValue); | |||
| 29338 | real_t fpsScale = getFPSScale(144.0); | |||
| 29339 | mpForegroundValue += fpsScale * (setpointDiff / 20.0); // reach it in 20 intervals, scaled to FPS | |||
| 29340 | mpForegroundValue = std::min(static_cast<real_t>(MPBar.animateSetpoint), mpForegroundValue); | |||
| 29341 | ||||
| 29342 | /*if ( abs(MPBar.animateSetpoint) - abs(mpForegroundValue) <= 1.0 ) | |||
| 29343 | { | |||
| 29344 | mpForegroundValue = MPBar.animateSetpoint; | |||
| 29345 | }*/ | |||
| 29346 | } | |||
| 29347 | else if ( mpForegroundValue > MPBar.animateSetpoint ) // losing MP, snap to value | |||
| 29348 | { | |||
| 29349 | mpForegroundValue = MPBar.animateSetpoint; | |||
| 29350 | } | |||
| 29351 | ||||
| 29352 | if ( mpFadedValue < MPBar.animateSetpoint ) | |||
| 29353 | { | |||
| 29354 | mpFadedValue = mpForegroundValue; | |||
| 29355 | MPBar.animateTicks = ticks; | |||
| 29356 | } | |||
| 29357 | else if ( mpFadedValue > MPBar.animateSetpoint ) | |||
| 29358 | { | |||
| 29359 | if ( ticks - MPBar.animateTicks > 30 /*|| stats[player.playernum]->MP <= 0*/ ) // fall after x ticks | |||
| 29360 | { | |||
| 29361 | real_t setpointDiff = std::max(0.1, mpFadedValue - MPBar.animateSetpoint); | |||
| 29362 | real_t fpsScale = getFPSScale(144.0); | |||
| 29363 | mpFadedValue -= fpsScale * (setpointDiff / 20.0); // reach it in 20 intervals, scaled to FPS | |||
| 29364 | mpFadedValue = std::max(static_cast<real_t>(MPBar.animateSetpoint), mpFadedValue); | |||
| 29365 | } | |||
| 29366 | } | |||
| 29367 | else | |||
| 29368 | { | |||
| 29369 | MPBar.animateTicks = ticks; | |||
| 29370 | } | |||
| 29371 | ||||
| 29372 | char playerMPText[16]; | |||
| 29373 | snprintf(playerMPText, sizeof(playerMPText), "%d", stats[player.playernum]->MP); | |||
| 29374 | ||||
| 29375 | auto mpText = mpForegroundFrame->findField("mp text"); | |||
| 29376 | mpText->setText(playerMPText); | |||
| 29377 | ||||
| 29378 | real_t foregroundPercent = mpForegroundValue / MPBar.maxValue; | |||
| 29379 | mpProgress->pos.w = std::max(1, static_cast<int>((progressWidth)* foregroundPercent)); | |||
| 29380 | mpProgressEndCap->pos.x = mpProgress->pos.x + mpProgress->pos.w; | |||
| 29381 | ||||
| 29382 | real_t fadePercent = mpFadedValue / MPBar.maxValue; | |||
| 29383 | mpFaded->pos.w = std::max(1, static_cast<int>((progressWidth)* fadePercent)); | |||
| 29384 | mpFadedEndCap->pos.x = mpFaded->pos.x + mpFaded->pos.w; | |||
| 29385 | if ( mpFaded->pos.w == 1 && stats[player.playernum]->MP <= 0 ) | |||
| 29386 | { | |||
| 29387 | mpFaded->disabled = true; | |||
| 29388 | real_t opacity = mpFadeFrame->getOpacity(); | |||
| 29389 | real_t opacityChange = .5 * getFPSScale(144.0); // change by .05% independant of fps | |||
| 29390 | mpFadeFrame->setOpacity(std::max(0.0, opacity - opacityChange)); | |||
| 29391 | ||||
| 29392 | // make this element fade out to the left, starting 54px then finally at 40px. @ 40px it's out of shot (6 width + 8 endcap width) | |||
| 29393 | mpFadedBase->pos.x = 54 - (14 * (1.0 - opacity / 100.0)); | |||
| 29394 | mpFadedEndCap->pos.x = mpFadedBase->pos.x + mpFadedBase->pos.w; | |||
| 29395 | } | |||
| 29396 | else | |||
| 29397 | { | |||
| 29398 | mpFaded->disabled = false; | |||
| 29399 | mpFadeFrame->setOpacity(100.0); | |||
| 29400 | ||||
| 29401 | // reset to 54px left as we altered in above if statement | |||
| 29402 | mpFadedBase->pos.x = 54; | |||
| 29403 | } | |||
| 29404 | ||||
| 29405 | if ( stats[player.playernum]->MP <= 0 ) | |||
| 29406 | { | |||
| 29407 | // hide all the progress elements when dead, as endcap/base don't shrink | |||
| 29408 | // mpProgress width 0px defaults to original size, so hide that too | |||
| 29409 | mpProgress->disabled = true; | |||
| 29410 | mpProgressEndCap->disabled = true; | |||
| 29411 | mpProgressBot->disabled = true; | |||
| 29412 | } | |||
| 29413 | else | |||
| 29414 | { | |||
| 29415 | mpProgress->disabled = false; | |||
| 29416 | mpProgressEndCap->disabled = false; | |||
| 29417 | mpProgressBot->disabled = false; | |||
| 29418 | } | |||
| 29419 | ||||
| 29420 | // dividers | |||
| 29421 | { | |||
| 29422 | const int fullBarWidth = mpProgressBot->pos.w + progressWidth + mpEndcap->pos.w / 2; | |||
| 29423 | auto div25Percent = mpForegroundFrame->findImage("mp img div 25pc"); | |||
| 29424 | div25Percent->disabled = false; | |||
| 29425 | div25Percent->pos.x = mpProgressBot->pos.x + fullBarWidth * .25 - 2; | |||
| 29426 | auto div50Percent = mpForegroundFrame->findImage("mp img div 50pc"); | |||
| 29427 | div50Percent->disabled = false; | |||
| 29428 | div50Percent->pos.x = mpProgressBot->pos.x + fullBarWidth * .5 - 2; | |||
| 29429 | auto div75Percent = mpForegroundFrame->findImage("mp img div 75pc"); | |||
| 29430 | div75Percent->disabled = false; | |||
| 29431 | div75Percent->pos.x = mpProgressBot->pos.x + fullBarWidth * .75 - 2; | |||
| 29432 | ||||
| 29433 | if ( div50Percent->pos.x - div25Percent->pos.x < HPMPdividerThresholdInterval ) | |||
| 29434 | { | |||
| 29435 | div75Percent->disabled = true; | |||
| 29436 | // 2 dividers 33%/66% | |||
| 29437 | div25Percent->pos.x = mpProgressBot->pos.x + fullBarWidth * .33 - 2; | |||
| 29438 | div50Percent->pos.x = mpProgressBot->pos.x + fullBarWidth * .66 - 2; | |||
| 29439 | if ( div50Percent->pos.x - div25Percent->pos.x < HPMPdividerThresholdInterval ) | |||
| 29440 | { | |||
| 29441 | // 1 divider 50% | |||
| 29442 | div25Percent->disabled = true; | |||
| 29443 | div50Percent->pos.x = mpProgressBot->pos.x + fullBarWidth * .5 - 2; | |||
| 29444 | } | |||
| 29445 | } | |||
| 29446 | } | |||
| 29447 | ||||
| 29448 | mpProgress->path = MPBarPaths_t::get(player.playernum, "mp img progress"); | |||
| 29449 | mpProgressBot->path = MPBarPaths_t::get(player.playernum, "mp img progress bot"); | |||
| 29450 | mpProgressEndCap->path = MPBarPaths_t::get(player.playernum, "mp img progress endcap"); | |||
| 29451 | auto mpProgressEndCapFlash = mpForegroundFrame->findImage("mp img progress endcap flash"); | |||
| 29452 | mpProgressEndCapFlash->disabled = true; | |||
| 29453 | const int framesPerAnimation = (MPBar.flashType == FLASH_ON_DAMAGE ? 1 : 2)/* * *cvar_hpanimdebug*/; | |||
| 29454 | const int numAnimationFrames = (MPBar.flashType == FLASH_ON_DAMAGE ? 30 : 2)/* * *cvar_hpanimdebug*/; | |||
| 29455 | if ( MPBar.flashTicks > 0 ) | |||
| 29456 | { | |||
| 29457 | if ( MPBar.flashAnimState > numAnimationFrames || mpProgress->disabled ) | |||
| 29458 | { | |||
| 29459 | MPBar.flashTicks = 0; | |||
| 29460 | MPBar.flashType = FLASH_ON_DAMAGE; | |||
| 29461 | MPBar.flashAnimState = -1; | |||
| 29462 | mpProgressEndCapFlash->disabled = true; | |||
| 29463 | } | |||
| 29464 | else | |||
| 29465 | { | |||
| 29466 | mpProgressEndCapFlash->disabled = mpProgressEndCap->disabled; | |||
| 29467 | bool processedOnTick = MPBar.flashProcessedOnTick == ticks; | |||
| 29468 | if ( ticks == MPBar.flashTicks ) | |||
| 29469 | { | |||
| 29470 | MPBar.flashAnimState = 1; | |||
| 29471 | MPBar.flashProcessedOnTick = ticks; | |||
| 29472 | ||||
| 29473 | if ( mpProgressEndCapFlash->path == MPBarPaths_t::get(player.playernum, "mp img progress endcap flash 1") | |||
| 29474 | || mpProgressEndCapFlash->path == MPBarPaths_t::get(player.playernum, "mp img progress endcap flash 2") | |||
| 29475 | || mpProgressEndCapFlash->path == MPBarPaths_t::get(player.playernum, "mp img progress endcap flash 3") ) | |||
| 29476 | { | |||
| 29477 | mpProgressEndCapFlash->path = MPBarPaths_t::get(player.playernum, "mp img progress endcap flash"); // reset to no full flash | |||
| 29478 | } | |||
| 29479 | } | |||
| 29480 | else if ( (!processedOnTick) | |||
| 29481 | && (ticks > MPBar.flashTicks) | |||
| 29482 | && (ticks - MPBar.flashTicks) % framesPerAnimation == 0 ) | |||
| 29483 | { | |||
| 29484 | ++MPBar.flashAnimState; | |||
| 29485 | MPBar.flashProcessedOnTick = ticks; | |||
| 29486 | } | |||
| 29487 | ||||
| 29488 | if ( MPBar.flashType == 0 ) | |||
| 29489 | { | |||
| 29490 | if ( MPBar.flashAnimState <= 16 && MPBar.flashAnimState >= 10 ) | |||
| 29491 | { | |||
| 29492 | mpProgressEndCapFlash->color = 0xFFFFFFFF; | |||
| 29493 | } | |||
| 29494 | else if ( MPBar.flashAnimState == 0 ) | |||
| 29495 | { | |||
| 29496 | mpProgressEndCapFlash->color = makeColor(255, 255, 255, 0); | |||
| 29497 | mpProgressEndCapFlash->path = MPBarPaths_t::get(player.playernum, "mp img progress endcap flash"); | |||
| 29498 | } | |||
| 29499 | ||||
| 29500 | if ( MPBar.flashAnimState <= 9 ) | |||
| 29501 | { | |||
| 29502 | if ( MPBar.flashAnimState == 7 ) | |||
| 29503 | { | |||
| 29504 | // we need the MP bar to flash long enough for long spellcast times | |||
| 29505 | // can adjust how many animStates we skip here to play with timing, | |||
| 29506 | // without changing other state machine code | |||
| 29507 | MPBar.flashAnimState = 9; // 1, 2 skip a few.. | |||
| 29508 | } | |||
| 29509 | Uint8 r, g, b, a; | |||
| 29510 | getColor(mpProgressEndCapFlash->color, &r, &g, &b, &a); | |||
| 29511 | int increment = 10; | |||
| 29512 | real_t fpsScale = getFPSScale(60.0); | |||
| 29513 | increment *= fpsScale; | |||
| 29514 | a = std::min(255, (int)a + increment); | |||
| 29515 | mpProgressEndCapFlash->color = makeColor(r, g, b, a); | |||
| 29516 | ||||
| 29517 | mpProgress->path = MPBarPaths_t::get(player.playernum, "mp img progress"); | |||
| 29518 | mpProgressBot->path = MPBarPaths_t::get(player.playernum, "mp img progress bot"); | |||
| 29519 | ||||
| 29520 | if ( MPBar.flashAnimState % 2 == 0 | |||
| 29521 | && !processedOnTick ) | |||
| 29522 | { | |||
| 29523 | if ( mpProgressEndCapFlash->path == MPBarPaths_t::get(player.playernum, "mp img progress endcap flash") ) | |||
| 29524 | { | |||
| 29525 | mpProgressEndCapFlash->path = MPBarPaths_t::get(player.playernum, "mp img progress endcap flash b"); | |||
| 29526 | } | |||
| 29527 | else if ( mpProgressEndCapFlash->path == MPBarPaths_t::get(player.playernum, "mp img progress endcap flash b") ) | |||
| 29528 | { | |||
| 29529 | mpProgressEndCapFlash->path = MPBarPaths_t::get(player.playernum, "mp img progress endcap flash c"); | |||
| 29530 | } | |||
| 29531 | else if ( mpProgressEndCapFlash->path == MPBarPaths_t::get(player.playernum, "mp img progress endcap flash c") ) | |||
| 29532 | { | |||
| 29533 | mpProgressEndCapFlash->path = MPBarPaths_t::get(player.playernum, "mp img progress endcap flash d"); | |||
| 29534 | } | |||
| 29535 | else | |||
| 29536 | { | |||
| 29537 | mpProgressEndCapFlash->path = MPBarPaths_t::get(player.playernum, "mp img progress endcap flash"); | |||
| 29538 | } | |||
| 29539 | } | |||
| 29540 | } | |||
| 29541 | else if ( MPBar.flashAnimState <= 10 ) | |||
| 29542 | { | |||
| 29543 | mpProgress->path = MPBarPaths_t::get(player.playernum, "mp img progress"); | |||
| 29544 | mpProgressEndCapFlash->path = MPBarPaths_t::get(player.playernum, "mp img progress endcap flash"); | |||
| 29545 | mpProgressBot->path = MPBarPaths_t::get(player.playernum, "mp img progress bot"); | |||
| 29546 | } | |||
| 29547 | else if ( MPBar.flashAnimState >= 11 && MPBar.flashAnimState <= 12 ) | |||
| 29548 | { | |||
| 29549 | mpProgress->path = MPBarPaths_t::get(player.playernum, "mp img progress 1"); | |||
| 29550 | mpProgressEndCapFlash->path = MPBarPaths_t::get(player.playernum, "mp img progress endcap flash 1"); | |||
| 29551 | mpProgressBot->path = MPBarPaths_t::get(player.playernum, "mp img progress bot 1"); | |||
| 29552 | } | |||
| 29553 | else if ( MPBar.flashAnimState == 13 ) | |||
| 29554 | { | |||
| 29555 | mpProgress->path = MPBarPaths_t::get(player.playernum, "mp img progress 2"); | |||
| 29556 | mpProgressEndCapFlash->path = MPBarPaths_t::get(player.playernum, "mp img progress endcap flash 2"); | |||
| 29557 | mpProgressBot->path = MPBarPaths_t::get(player.playernum, "mp img progress bot 2"); | |||
| 29558 | } | |||
| 29559 | else if ( MPBar.flashAnimState >= 14 && MPBar.flashAnimState <= 15 ) | |||
| 29560 | { | |||
| 29561 | mpProgress->path = MPBarPaths_t::get(player.playernum, "mp img progress 1"); | |||
| 29562 | mpProgressEndCapFlash->path = MPBarPaths_t::get(player.playernum, "mp img progress endcap flash 1"); | |||
| 29563 | mpProgressBot->path = MPBarPaths_t::get(player.playernum, "mp img progress bot 1"); | |||
| 29564 | } | |||
| 29565 | else if ( MPBar.flashAnimState == 16 ) | |||
| 29566 | { | |||
| 29567 | mpProgress->path = MPBarPaths_t::get(player.playernum, "mp img progress 3"); | |||
| 29568 | mpProgressEndCapFlash->path = MPBarPaths_t::get(player.playernum, "mp img progress endcap flash 3"); | |||
| 29569 | mpProgressBot->path = MPBarPaths_t::get(player.playernum, "mp img progress bot 3"); | |||
| 29570 | } | |||
| 29571 | else | |||
| 29572 | { | |||
| 29573 | mpProgress->path = MPBarPaths_t::get(player.playernum, "mp img progress"); | |||
| 29574 | mpProgressEndCapFlash->path = MPBarPaths_t::get(player.playernum, "mp img progress endcap flash 4"); | |||
| 29575 | Uint8 r, g, b, a; | |||
| 29576 | getColor(mpProgressEndCapFlash->color, &r, &g, &b, &a); | |||
| 29577 | int decrement = 20; | |||
| 29578 | real_t fpsScale = getFPSScale(60.0); | |||
| 29579 | decrement *= fpsScale; | |||
| 29580 | a = std::max(0, (int)a - decrement); | |||
| 29581 | mpProgressEndCapFlash->color = makeColor(r, g, b, a); | |||
| 29582 | } | |||
| 29583 | } | |||
| 29584 | else | |||
| 29585 | { | |||
| 29586 | mpProgressEndCapFlash->color = 0xFFFFFFFF; | |||
| 29587 | mpProgressEndCapFlash->disabled = true; | |||
| 29588 | if ( MPBar.flashAnimState == 1 ) | |||
| 29589 | { | |||
| 29590 | mpProgress->path = MPBarPaths_t::get(player.playernum, "mp img progress 3"); | |||
| 29591 | mpProgressBot->path = MPBarPaths_t::get(player.playernum, "mp img progress bot 3"); | |||
| 29592 | mpProgressEndCap->path = MPBarPaths_t::get(player.playernum, "mp img progress endcap 1"); | |||
| 29593 | } | |||
| 29594 | } | |||
| 29595 | } | |||
| 29596 | } | |||
| 29597 | else | |||
| 29598 | { | |||
| 29599 | MPBar.flashAnimState = -1; | |||
| 29600 | mpProgressEndCapFlash->disabled = true; | |||
| 29601 | } | |||
| 29602 | ||||
| 29603 | { | |||
| 29604 | mpProgressEndCapFlash->pos.w = 22; | |||
| 29605 | mpProgressEndCapFlash->section.x = 0; | |||
| 29606 | mpProgressEndCapFlash->section.w = 0; | |||
| 29607 | if ( !mpProgressEndCap->disabled ) | |||
| 29608 | { | |||
| 29609 | mpProgressEndCapFlash->pos.x = mpProgressEndCap->pos.x - (mpProgressEndCapFlash->pos.w - mpProgressEndCap->pos.w); | |||
| 29610 | } | |||
| 29611 | if ( mpProgressEndCapFlash->pos.x < mpProgressBot->pos.x ) | |||
| 29612 | { | |||
| 29613 | // adjust end cap flash to clip correctly sliding past end of bar | |||
| 29614 | int overflowx = (mpProgressBot->pos.x - mpProgressEndCapFlash->pos.x); | |||
| 29615 | mpProgressEndCapFlash->section.x = (overflowx); | |||
| 29616 | mpProgressEndCapFlash->pos.x += overflowx; | |||
| 29617 | mpProgressEndCapFlash->pos.w -= overflowx; | |||
| 29618 | mpProgressEndCapFlash->section.w = mpProgressEndCapFlash->pos.w; | |||
| 29619 | } | |||
| 29620 | } | |||
| 29621 | ||||
| 29622 | if ( player.magic.noManaProcessedOnTick != 0 ) | |||
| 29623 | { | |||
| 29624 | if ( ticks != player.magic.noManaProcessedOnTick ) | |||
| 29625 | { | |||
| 29626 | ++player.magic.noManaFeedbackTicks; | |||
| 29627 | player.magic.noManaProcessedOnTick = ticks; | |||
| 29628 | } | |||
| 29629 | if ( player.magic.noManaFeedbackTicks > TICKS_PER_SECOND50 ) | |||
| 29630 | { | |||
| 29631 | player.magic.noManaProcessedOnTick = 0; | |||
| 29632 | player.magic.noManaFeedbackTicks = 0; | |||
| 29633 | } | |||
| 29634 | } | |||
| 29635 | ||||
| 29636 | mpFrame->setDisabled(player.ghost.isActive()); | |||
| 29637 | } | |||
| 29638 | ||||
| 29639 | bool hotbar_slot_t::matchesExactLastItem(int player, Item* item) | |||
| 29640 | { | |||
| 29641 | if ( !item ) { return false; } | |||
| 29642 | if ( lastItem.uid == item->uid ) { return true; } | |||
| 29643 | if ( lastItem.type == item->type | |||
| 29644 | && lastItem.status == item->status | |||
| 29645 | && lastItem.count == item->count | |||
| 29646 | && lastItem.identified == item->identified ) | |||
| 29647 | { | |||
| 29648 | if ( item->shouldItemStack(player, true) ) | |||
| 29649 | { | |||
| 29650 | return true; | |||
| 29651 | } | |||
| 29652 | else | |||
| 29653 | { | |||
| 29654 | return lastItem.appearance == item->appearance; | |||
| 29655 | } | |||
| 29656 | } | |||
| 29657 | return false; | |||
| 29658 | } | |||
| 29659 | ||||
| 29660 | void hotbar_slot_t::resetLastItem() | |||
| 29661 | { | |||
| 29662 | lastCategory = -1; | |||
| 29663 | lastItem.type = WOODEN_SHIELD; | |||
| 29664 | lastItem.appearance = -1; | |||
| 29665 | lastItem.status = BROKEN; | |||
| 29666 | lastItem.count = 0; | |||
| 29667 | lastItem.identified = false; | |||
| 29668 | lastItem.uid = 0; | |||
| 29669 | } | |||
| 29670 | ||||
| 29671 | void hotbar_slot_t::storeLastItem(Item* item) | |||
| 29672 | { | |||
| 29673 | if ( !item ) { return; } | |||
| 29674 | if ( !item->identified ) { return; } | |||
| 29675 | lastItem.type = item->type; | |||
| 29676 | lastItem.appearance = item->appearance; | |||
| 29677 | lastItem.status = item->status; | |||
| 29678 | lastItem.count = item->count; | |||
| 29679 | lastItem.identified = item->identified; | |||
| 29680 | lastItem.uid = item->uid; | |||
| 29681 | lastCategory = itemCategory(item); | |||
| 29682 | } | |||
| 29683 | ||||
| 29684 | std::string hotbarSlotBindingText(const int player, const int slotnum, const Input::binding_t& binding) | |||
| 29685 | { | |||
| 29686 | std::string inputName = ""; | |||
| 29687 | if ( binding.type == Input::binding_t::KEYBOARD && binding.keycode != SDLK_UNKNOWN ) | |||
| 29688 | { | |||
| 29689 | if ( binding.keycode >= SDLK_0 && binding.keycode <= SDLK_9 ) | |||
| 29690 | { | |||
| 29691 | inputName = SDL_GetKeyName(binding.keycode); | |||
| 29692 | } | |||
| 29693 | } | |||
| 29694 | else if ( binding.type != Input::binding_t::MOUSE_BUTTON ) | |||
| 29695 | { | |||
| 29696 | if ( slotnum + 1 == 10 ) | |||
| 29697 | { | |||
| 29698 | inputName = "0"; | |||
| 29699 | } | |||
| 29700 | else | |||
| 29701 | { | |||
| 29702 | inputName = std::to_string(slotnum + 1); | |||
| 29703 | } | |||
| 29704 | } | |||
| 29705 | return inputName; | |||
| 29706 | } | |||
| 29707 | ||||
| 29708 | void Player::Hotbar_t::updateHotbar() | |||
| 29709 | { | |||
| 29710 | if ( !hotbarFrame ) | |||
| 29711 | { | |||
| 29712 | return; | |||
| 29713 | } | |||
| 29714 | ||||
| 29715 | hotbarFrame->setOpacity(hotbarFrame->getParent()->getOpacity()); | |||
| 29716 | bool tempHideHotbar = false; | |||
| 29717 | if ( player.ghost.isActive() ) | |||
| 29718 | { | |||
| 29719 | tempHideHotbar = true; | |||
| 29720 | } | |||
| 29721 | else if ( player.bUseCompactGUIHeight() | |||
| 29722 | && (player.gui_mode == GUI_MODE_FOLLOWERMENU | |||
| 29723 | || player.gui_mode == GUI_MODE_CALLOUT | |||
| 29724 | || (player.hud.compactLayoutMode == Player::HUD_t::COMPACT_LAYOUT_CHARSHEET && !player.shootmode) | |||
| 29725 | || (player.gui_mode == GUI_MODE_MAGIC) | |||
| 29726 | || (player.shopGUI.bOpen) | |||
| 29727 | || (player.inventoryUI.chestGUI.bOpen) | |||
| 29728 | || player.minimap.mapWindow | |||
| 29729 | || player.messageZone.logWindow | |||
| 29730 | || (GenericGUI[player.playernum].isGUIOpen()) | |||
| 29731 | ) ) | |||
| 29732 | { | |||
| 29733 | tempHideHotbar = true; | |||
| 29734 | } | |||
| 29735 | else if ( (!player.bUseCompactGUIHeight() && player.bUseCompactGUIWidth()) | |||
| 29736 | && (player.hud.compactLayoutMode == Player::HUD_t::COMPACT_LAYOUT_CHARSHEET && !player.shootmode) ) | |||
| 29737 | { | |||
| 29738 | tempHideHotbar = true; | |||
| 29739 | } | |||
| 29740 | if ( tempHideHotbar ) | |||
| 29741 | { | |||
| 29742 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 29743 | real_t setpointDiff = fpsScale * std::max(.1, (1.0 - animHide)) / 2.5; | |||
| 29744 | animHide += setpointDiff; | |||
| 29745 | animHide = std::min(1.0, animHide); | |||
| 29746 | isInteractable = true; | |||
| 29747 | } | |||
| 29748 | else | |||
| 29749 | { | |||
| 29750 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 29751 | real_t setpointDiff = fpsScale * std::max(.1, (animHide)) / 2.5; | |||
| 29752 | animHide -= setpointDiff; | |||
| 29753 | animHide = std::max(0.0, animHide); | |||
| 29754 | if ( animHide <= 0.001 ) | |||
| 29755 | { | |||
| 29756 | isInteractable = true; | |||
| 29757 | } | |||
| 29758 | } | |||
| 29759 | ||||
| 29760 | if ( player.bUseCompactGUIHeight() && player.bUseCompactGUIWidth() | |||
| 29761 | && !player.shootmode && player.GUI.activeModule != Player::GUI_t::MODULE_HOTBAR ) | |||
| 29762 | { | |||
| 29763 | hotbarFrame->setOpacity(75.0); | |||
| 29764 | } | |||
| 29765 | ||||
| 29766 | bool bCompactView = false; | |||
| 29767 | bool loweredY = false; | |||
| 29768 | int compactDisableLeftRightOffsetX = 0; | |||
| 29769 | if ( (keystatus[SDLK_u] && enableDebugKeys) || player.bUseCompactGUIWidth() ) | |||
| 29770 | { | |||
| 29771 | if ( !*cvar_hotbar_compact_disable ) | |||
| 29772 | { | |||
| 29773 | bCompactView = true; | |||
| 29774 | } | |||
| 29775 | else | |||
| 29776 | { | |||
| 29777 | compactDisableLeftRightOffsetX = 8; | |||
| 29778 | } | |||
| 29779 | loweredY = true; | |||
| 29780 | } | |||
| 29781 | else if ( player.bUseCompactGUIHeight() ) | |||
| 29782 | { | |||
| 29783 | loweredY = true; | |||
| 29784 | } | |||
| 29785 | int hotbarStartY1 = hotbarFrame->getSize().h + getHotbarStartY1(); // higher row (center group) | |||
| 29786 | int hotbarStartY2 = hotbarFrame->getSize().h + getHotbarStartY2(); // lower row (left/right) | |||
| 29787 | hotbarStartY1 += ((bCompactView || loweredY) ? hotbarCompactOffsetY : hotbarOffsetY); | |||
| 29788 | hotbarStartY2 += ((bCompactView || loweredY) ? hotbarCompactOffsetY : hotbarOffsetY); | |||
| 29789 | ||||
| 29790 | static ConsoleVariable<int> cvar_hotbar_splitscreen_center_x("/hotbar_splitscreen_center_x", 0); | |||
| 29791 | const int hotbarCentreX = (hotbarFrame->getSize().w / 2) + *cvar_hotbar_splitscreen_center_x; | |||
| 29792 | int hotbarCentreXLeft = hotbarCentreX - 148 + (bCompactView ? hotbarCompactOffsetX : compactDisableLeftRightOffsetX); | |||
| 29793 | int hotbarCentreXRight = hotbarCentreX + 148 - (bCompactView ? hotbarCompactOffsetX : compactDisableLeftRightOffsetX); | |||
| 29794 | hotbarStartY1 += animHide * abs(getHotbarStartY1()); | |||
| 29795 | hotbarStartY2 += animHide * abs(getHotbarStartY1()); | |||
| 29796 | ||||
| 29797 | if ( !player.shootmode || FollowerMenu[player.playernum].followerMenuIsOpen() | |||
| 29798 | || CalloutMenu[player.playernum].calloutMenuIsOpen() ) | |||
| 29799 | { | |||
| 29800 | if (player.hotbar.useHotbarFaceMenu) | |||
| 29801 | { | |||
| 29802 | if ( Input::inputs[player.playernum].binaryToggle("Hotbar Down / Cancel") ) | |||
| 29803 | { | |||
| 29804 | Input::inputs[player.playernum].consumeBinaryToggle("Hotbar Down / Cancel"); | |||
| 29805 | } | |||
| 29806 | if ( Input::inputs[player.playernum].binaryToggle("Hotbar Left") ) | |||
| 29807 | { | |||
| 29808 | Input::inputs[player.playernum].consumeBinaryToggle("Hotbar Left"); | |||
| 29809 | } | |||
| 29810 | if ( Input::inputs[player.playernum].binaryToggle("Hotbar Up / Select") ) | |||
| 29811 | { | |||
| 29812 | Input::inputs[player.playernum].consumeBinaryToggle("Hotbar Up / Select"); | |||
| 29813 | } | |||
| 29814 | if ( Input::inputs[player.playernum].binaryToggle("Hotbar Right") ) | |||
| 29815 | { | |||
| 29816 | Input::inputs[player.playernum].consumeBinaryToggle("Hotbar Right"); | |||
| 29817 | } | |||
| 29818 | } | |||
| 29819 | faceMenuButtonHeld = FaceMenuGroup::GROUP_NONE; | |||
| 29820 | } | |||
| 29821 | ||||
| 29822 | bool faceMenuSnapCursorInstantly = false; | |||
| 29823 | if ( faceMenuButtonHeld != FaceMenuGroup::GROUP_NONE || (player.GUI.activeModule == Player::GUI_t::MODULE_HOTBAR && !player.shootmode) ) | |||
| 29824 | { | |||
| 29825 | if ( selectedSlotAnimateCurrentValue == 0.0 ) | |||
| 29826 | { | |||
| 29827 | faceMenuSnapCursorInstantly = true; | |||
| 29828 | } | |||
| 29829 | real_t fpsScale = getFPSScale(144.0); | |||
| 29830 | real_t setpointDiff = std::max(0.1, 1.0 - selectedSlotAnimateCurrentValue); | |||
| 29831 | selectedSlotAnimateCurrentValue += fpsScale * (setpointDiff / 10.0); | |||
| 29832 | selectedSlotAnimateCurrentValue = std::min(1.0, selectedSlotAnimateCurrentValue); | |||
| 29833 | } | |||
| 29834 | else | |||
| 29835 | { | |||
| 29836 | selectedSlotAnimateCurrentValue = 0.0; | |||
| 29837 | } | |||
| 29838 | ||||
| 29839 | auto highlightSlot = hotbarFrame->findFrame("hotbar highlight"); | |||
| 29840 | auto highlightSlotImg = highlightSlot->findImage("highlight img"); | |||
| 29841 | highlightSlotImg->disabled = true; | |||
| 29842 | auto highlightNumText = highlightSlot->findField("slot num text"); | |||
| 29843 | highlightNumText->setDisabled(true); | |||
| 29844 | ||||
| 29845 | auto shootmodeSelectedSlotCursor = hotbarFrame->findFrame("shootmode selected item cursor"); | |||
| 29846 | if ( shootmodeSelectedSlotCursor ) | |||
| 29847 | { | |||
| 29848 | shootmodeSelectedSlotCursor->setDisabled(true); | |||
| 29849 | } | |||
| 29850 | ||||
| 29851 | if ( player.shootmode || !inputs.getUIInteraction(player.playernum)->selectedItem ) | |||
| 29852 | { | |||
| 29853 | if ( auto oldSelectedItemFrame = hotbarFrame->findFrame("hotbar old selected item") ) | |||
| 29854 | { | |||
| 29855 | oldSelectedItemFrame->setDisabled(true); | |||
| 29856 | } | |||
| 29857 | } | |||
| 29858 | ||||
| 29859 | auto cancelPromptTxt = hotbarFrame->findField("hotbar cancel prompt"); | |||
| 29860 | cancelPromptTxt->setDisabled(true); | |||
| 29861 | auto cancelPromptGlyph = hotbarFrame->findImage("hotbar cancel glyph"); | |||
| 29862 | cancelPromptGlyph->disabled = true; | |||
| 29863 | ||||
| 29864 | if ( (!bCompactView && !loweredY) && useHotbarFaceMenu && faceMenuButtonHeld != FaceMenuGroup::GROUP_NONE ) | |||
| 29865 | { | |||
| 29866 | cancelPromptTxt->setDisabled(false); | |||
| 29867 | cancelPromptTxt->setText(Language::get(3063)); | |||
| 29868 | static ConsoleVariable<int> cvar_hotbar_cancel_prompt_y("/hotbar_cancel_prompt_y", -6); | |||
| 29869 | static ConsoleVariable<int> cvar_hotbar_cancel_prompt_x("/hotbar_cancel_prompt_x", 29); | |||
| 29870 | cancelPromptGlyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("Hotbar Down / Cancel"); | |||
| 29871 | if ( auto imgGet = Image::get(cancelPromptGlyph->path.c_str()) ) | |||
| 29872 | { | |||
| 29873 | cancelPromptGlyph->pos.w = imgGet->getWidth(); | |||
| 29874 | cancelPromptGlyph->pos.h = imgGet->getHeight(); | |||
| 29875 | cancelPromptGlyph->disabled = false; | |||
| 29876 | } | |||
| 29877 | SDL_Rect promptTxtPos = cancelPromptTxt->getSize(); | |||
| 29878 | promptTxtPos.x = hotbarCentreX + *cvar_hotbar_cancel_prompt_x; | |||
| 29879 | promptTxtPos.y = hotbarStartY1 + getSlotSize() - 2; | |||
| 29880 | if ( auto textGet = cancelPromptTxt->getTextObject() ) | |||
| 29881 | { | |||
| 29882 | promptTxtPos.x -= textGet->getWidth() / 2; | |||
| 29883 | promptTxtPos.x += cancelPromptGlyph->pos.w / 2 + 2; | |||
| 29884 | if ( promptTxtPos.x % 2 == 1 ) | |||
| 29885 | { | |||
| 29886 | ++promptTxtPos.x; | |||
| 29887 | } | |||
| 29888 | } | |||
| 29889 | cancelPromptGlyph->pos.y = promptTxtPos.y + *cvar_hotbar_cancel_prompt_y; | |||
| 29890 | cancelPromptGlyph->pos.x = promptTxtPos.x - 4 - cancelPromptGlyph->pos.w; | |||
| 29891 | cancelPromptTxt->setSize(promptTxtPos); | |||
| 29892 | } | |||
| 29893 | ||||
| 29894 | // position the slots | |||
| 29895 | for ( int num = 0; num < NUM_HOTBAR_SLOTS; ++num ) | |||
| 29896 | { | |||
| 29897 | if ( hotbar[num].item != 0 ) | |||
| 29898 | { | |||
| 29899 | if ( Item* item = uidToItem(hotbar[num].item) ) | |||
| 29900 | { | |||
| 29901 | if ( hotbar[num].item == hotbar[num].lastItem.uid | |||
| 29902 | && hotbar[num].lastItem.status > BROKEN | |||
| 29903 | && item->status == BROKEN ) | |||
| 29904 | { | |||
| 29905 | // de-hotbar newly broken stuff | |||
| 29906 | hotbar[num].item = 0; | |||
| 29907 | hotbar[num].resetLastItem(); | |||
| 29908 | } | |||
| 29909 | else | |||
| 29910 | { | |||
| 29911 | hotbar[num].storeLastItem(item); | |||
| 29912 | } | |||
| 29913 | } | |||
| 29914 | } | |||
| 29915 | ||||
| 29916 | auto slot = getHotbarSlotFrame(num); | |||
| 29917 | assert(slot)(static_cast<void> (0)); | |||
| 29918 | ||||
| 29919 | if ( auto img = slot->findImage("slot img") ) // apply any opacity from config | |||
| 29920 | { | |||
| 29921 | Uint8 r, g, b, a; | |||
| 29922 | getColor(img->color, &r, &g, &b, &a); | |||
| 29923 | a = hotbarSlotOpacity; | |||
| 29924 | img->color = makeColor( r, g, b, a); | |||
| 29925 | } | |||
| 29926 | if ( highlightSlotImg ) | |||
| 29927 | { | |||
| 29928 | Uint8 r, g, b, a; | |||
| 29929 | getColor(highlightSlotImg->color, &r, &g, &b, &a); | |||
| 29930 | a = hotbarSelectedSlotOpacity; | |||
| 29931 | highlightSlotImg->color = makeColor( r, g, b, a); | |||
| 29932 | } | |||
| 29933 | ||||
| 29934 | char glyphname[32]; | |||
| 29935 | snprintf(glyphname, sizeof(glyphname), "hotbar glyph %d", num); | |||
| 29936 | auto glyph = hotbarFrame->findImage(glyphname); | |||
| 29937 | assert(glyph)(static_cast<void> (0)); | |||
| 29938 | glyph->disabled = true; | |||
| 29939 | ||||
| 29940 | if ( useHotbarFaceMenu && num == 9 ) | |||
| 29941 | { | |||
| 29942 | slot->setDisabled(true); | |||
| 29943 | } | |||
| 29944 | else | |||
| 29945 | { | |||
| 29946 | slot->setDisabled(false); | |||
| 29947 | } | |||
| 29948 | ||||
| 29949 | SDL_Rect pos = slot->getSize(); | |||
| 29950 | int compactViewOffset = 0; | |||
| 29951 | int compactInactiveSlotOffset = 0; | |||
| 29952 | int compactExpandedOffsetX = 0; | |||
| 29953 | int centreXLeft = hotbarCentreXLeft; | |||
| 29954 | int centreXRight = hotbarCentreXRight; | |||
| 29955 | int centreX = hotbarCentreX; | |||
| 29956 | bool compactViewNavigation = (player.GUI.activeModule == Player::GUI_t::MODULE_HOTBAR && !player.shootmode) | |||
| 29957 | || *cvar_hotbar_compact_use_fullsize; | |||
| 29958 | if ( bCompactView ) | |||
| 29959 | { | |||
| 29960 | if ( compactViewNavigation ) | |||
| 29961 | { | |||
| 29962 | compactViewOffset = pos.w * hotbarCompactSlotOverlapPercent / 2.0; | |||
| 29963 | ||||
| 29964 | compactExpandedOffsetX = hotbarCompactExpandedOffsetX; | |||
| 29965 | centreXLeft -= compactExpandedOffsetX; | |||
| 29966 | centreXRight += compactExpandedOffsetX; | |||
| 29967 | } | |||
| 29968 | else | |||
| 29969 | { | |||
| 29970 | compactViewOffset = pos.w * hotbarCompactSlotOverlapPercent; | |||
| 29971 | } | |||
| 29972 | compactInactiveSlotOffset = (hotbarCompactInactiveSlotMovementX + (*cvar_hotbar_compact_use_fullsize ? -6 : 0)) | |||
| 29973 | * selectedSlotAnimateCurrentValue; | |||
| 29974 | ||||
| 29975 | if ( faceMenuButtonHeld != FaceMenuGroup::GROUP_NONE ) | |||
| 29976 | { | |||
| 29977 | if ( faceMenuButtonHeld == FaceMenuGroup::GROUP_LEFT ) | |||
| 29978 | { | |||
| 29979 | centreX += compactInactiveSlotOffset; | |||
| 29980 | centreXRight += compactInactiveSlotOffset; | |||
| 29981 | } | |||
| 29982 | else if( faceMenuButtonHeld == FaceMenuGroup::GROUP_MIDDLE ) | |||
| 29983 | { | |||
| 29984 | centreXLeft -= compactInactiveSlotOffset; | |||
| 29985 | centreXRight += compactInactiveSlotOffset; | |||
| 29986 | } | |||
| 29987 | else if ( faceMenuButtonHeld == FaceMenuGroup::GROUP_RIGHT ) | |||
| 29988 | { | |||
| 29989 | centreXLeft -= compactInactiveSlotOffset; | |||
| 29990 | centreX -= compactInactiveSlotOffset; | |||
| 29991 | } | |||
| 29992 | } | |||
| 29993 | } | |||
| 29994 | pos.x = centreX; | |||
| 29995 | pos.y = hotbarStartY2; | |||
| 29996 | ||||
| 29997 | int slotYMovement = pos.h / 4; | |||
| 29998 | ||||
| 29999 | auto slotItem = slot->findFrame("hotbar slot item"); | |||
| 30000 | slotItem->setDisabled(true); | |||
| 30001 | ||||
| 30002 | if ( useHotbarFaceMenu ) | |||
| 30003 | { | |||
| 30004 | GameController* controller = inputs.getController(player.playernum); | |||
| 30005 | if ( controller ) | |||
| 30006 | { | |||
| 30007 | glyph->disabled = slot->isDisabled(); | |||
| 30008 | if ( !player.shootmode || !player.entity ) | |||
| 30009 | { | |||
| 30010 | glyph->disabled = true; | |||
| 30011 | } | |||
| 30012 | } | |||
| 30013 | ||||
| 30014 | slot->findField("slot num text")->setDisabled(true); // disable the hotkey prompts per slot | |||
| 30015 | switch ( num ) | |||
| 30016 | { | |||
| 30017 | // left group | |||
| 30018 | case 0: | |||
| 30019 | pos.x = centreXLeft - pos.w / 2 - pos.w + 2 + compactViewOffset; | |||
| 30020 | if ( faceMenuButtonHeld == FaceMenuGroup::GROUP_LEFT ) | |||
| 30021 | { | |||
| 30022 | pos.y -= slotYMovement * selectedSlotAnimateCurrentValue; | |||
| 30023 | pos.x -= compactViewOffset * selectedSlotAnimateCurrentValue; | |||
| 30024 | } | |||
| 30025 | else | |||
| 30026 | { | |||
| 30027 | glyph->disabled = true; | |||
| 30028 | } | |||
| 30029 | glyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("HotbarFacebarModifierLeft"); | |||
| 30030 | break; | |||
| 30031 | case 1: | |||
| 30032 | pos.x = centreXLeft - pos.w / 2; | |||
| 30033 | pos.y -= slotYMovement; | |||
| 30034 | glyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("Hotbar Left", | |||
| 30035 | faceMenuButtonHeld == FaceMenuGroup::GROUP_LEFT); | |||
| 30036 | if ( faceMenuButtonHeld != FaceMenuGroup::GROUP_LEFT | |||
| 30037 | && faceMenuButtonHeld != FaceMenuGroup::GROUP_NONE ) | |||
| 30038 | { | |||
| 30039 | glyph->color = makeColor(255, 255, 255, 255 * (1.0 - selectedSlotAnimateCurrentValue / 2)); | |||
| 30040 | //glyph->disabled = true; | |||
| 30041 | } | |||
| 30042 | else | |||
| 30043 | { | |||
| 30044 | glyph->color = 0xFFFFFFFF; | |||
| 30045 | } | |||
| 30046 | break; | |||
| 30047 | case 2: | |||
| 30048 | pos.x = centreXLeft + (pos.w / 2 - 2) - compactViewOffset; | |||
| 30049 | if ( faceMenuButtonHeld == FaceMenuGroup::GROUP_LEFT ) | |||
| 30050 | { | |||
| 30051 | pos.y -= slotYMovement * selectedSlotAnimateCurrentValue; | |||
| 30052 | pos.x += compactViewOffset * selectedSlotAnimateCurrentValue; | |||
| 30053 | } | |||
| 30054 | else | |||
| 30055 | { | |||
| 30056 | glyph->disabled = true; | |||
| 30057 | } | |||
| 30058 | glyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("HotbarFacebarModifierRight"); | |||
| 30059 | break; | |||
| 30060 | // middle group | |||
| 30061 | case 3: | |||
| 30062 | pos.y = hotbarStartY1; | |||
| 30063 | pos.x = centreX - pos.w / 2 - pos.w + 2 + compactViewOffset; | |||
| 30064 | if ( faceMenuButtonHeld == FaceMenuGroup::GROUP_MIDDLE ) | |||
| 30065 | { | |||
| 30066 | pos.y -= slotYMovement * selectedSlotAnimateCurrentValue; | |||
| 30067 | pos.x -= compactViewOffset * selectedSlotAnimateCurrentValue; | |||
| 30068 | } | |||
| 30069 | else | |||
| 30070 | { | |||
| 30071 | glyph->disabled = true; | |||
| 30072 | } | |||
| 30073 | glyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("HotbarFacebarModifierLeft"); | |||
| 30074 | break; | |||
| 30075 | case 4: | |||
| 30076 | pos.y = hotbarStartY1; | |||
| 30077 | pos.y -= slotYMovement; | |||
| 30078 | pos.x = centreX - pos.w / 2; | |||
| 30079 | glyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("Hotbar Up / Select", | |||
| 30080 | faceMenuButtonHeld == FaceMenuGroup::GROUP_MIDDLE); | |||
| 30081 | if ( faceMenuButtonHeld != FaceMenuGroup::GROUP_MIDDLE | |||
| 30082 | && faceMenuButtonHeld != FaceMenuGroup::GROUP_NONE ) | |||
| 30083 | { | |||
| 30084 | glyph->color = makeColor(255, 255, 255, 255 * (1.0 - selectedSlotAnimateCurrentValue / 2)); | |||
| 30085 | //glyph->disabled = true; | |||
| 30086 | } | |||
| 30087 | else | |||
| 30088 | { | |||
| 30089 | glyph->color = 0xFFFFFFFF; | |||
| 30090 | } | |||
| 30091 | break; | |||
| 30092 | case 5: | |||
| 30093 | pos.y = hotbarStartY1; | |||
| 30094 | pos.x = centreX + (pos.w / 2 - 2) - compactViewOffset; | |||
| 30095 | if ( faceMenuButtonHeld == FaceMenuGroup::GROUP_MIDDLE ) | |||
| 30096 | { | |||
| 30097 | pos.y -= slotYMovement * selectedSlotAnimateCurrentValue; | |||
| 30098 | pos.x += compactViewOffset * selectedSlotAnimateCurrentValue; | |||
| 30099 | } | |||
| 30100 | else | |||
| 30101 | { | |||
| 30102 | glyph->disabled = true; | |||
| 30103 | } | |||
| 30104 | glyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("HotbarFacebarModifierRight"); | |||
| 30105 | break; | |||
| 30106 | // right group | |||
| 30107 | case 6: | |||
| 30108 | pos.x = centreXRight - pos.w / 2 - pos.w + 2 + compactViewOffset; | |||
| 30109 | if ( faceMenuButtonHeld == FaceMenuGroup::GROUP_RIGHT ) | |||
| 30110 | { | |||
| 30111 | pos.y -= slotYMovement * selectedSlotAnimateCurrentValue; | |||
| 30112 | pos.x -= compactViewOffset * selectedSlotAnimateCurrentValue; | |||
| 30113 | } | |||
| 30114 | else | |||
| 30115 | { | |||
| 30116 | glyph->disabled = true; | |||
| 30117 | } | |||
| 30118 | glyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("HotbarFacebarModifierLeft"); | |||
| 30119 | break; | |||
| 30120 | case 7: | |||
| 30121 | pos.x = centreXRight - pos.w / 2; | |||
| 30122 | pos.y -= slotYMovement; | |||
| 30123 | glyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("Hotbar Right", | |||
| 30124 | faceMenuButtonHeld == FaceMenuGroup::GROUP_RIGHT); | |||
| 30125 | if ( faceMenuButtonHeld != FaceMenuGroup::GROUP_RIGHT | |||
| 30126 | && faceMenuButtonHeld != FaceMenuGroup::GROUP_NONE ) | |||
| 30127 | { | |||
| 30128 | glyph->color = makeColor(255, 255, 255, 255 * (1.0 - selectedSlotAnimateCurrentValue / 2)); | |||
| 30129 | //glyph->disabled = true; | |||
| 30130 | } | |||
| 30131 | else | |||
| 30132 | { | |||
| 30133 | glyph->color = 0xFFFFFFFF; | |||
| 30134 | } | |||
| 30135 | break; | |||
| 30136 | case 8: | |||
| 30137 | pos.x = centreXRight + (pos.w / 2 - 2) - compactViewOffset; | |||
| 30138 | if ( faceMenuButtonHeld == FaceMenuGroup::GROUP_RIGHT ) | |||
| 30139 | { | |||
| 30140 | pos.y -= slotYMovement * selectedSlotAnimateCurrentValue; | |||
| 30141 | pos.x += compactViewOffset * selectedSlotAnimateCurrentValue; | |||
| 30142 | } | |||
| 30143 | else | |||
| 30144 | { | |||
| 30145 | glyph->disabled = true; | |||
| 30146 | } | |||
| 30147 | glyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("HotbarFacebarModifierRight"); | |||
| 30148 | break; | |||
| 30149 | default: | |||
| 30150 | break; | |||
| 30151 | } | |||
| 30152 | ||||
| 30153 | slot->setSize(pos); | |||
| 30154 | ||||
| 30155 | auto glyphImage = Image::get(glyph->path.c_str()); | |||
| 30156 | if ( glyphImage ) | |||
| 30157 | { | |||
| 30158 | glyph->pos.w = std::min((int)glyphImage->getWidth(), slot->getSize().w); | |||
| 30159 | glyph->pos.h = glyphImage->getHeight(); | |||
| 30160 | glyph->pos.x = pos.x + pos.w / 2 - glyph->pos.w / 2; | |||
| 30161 | glyph->pos.y = pos.y - glyph->pos.h; | |||
| 30162 | } | |||
| 30163 | } | |||
| 30164 | else | |||
| 30165 | { | |||
| 30166 | auto slot_text = slot->findField("slot num text"); | |||
| 30167 | slot_text->setDisabled(false); // enable the hotkey prompts per slot | |||
| 30168 | std::string slotstr = "Hotbar Slot " + std::to_string(num + 1); | |||
| 30169 | auto binding = Input::inputs[player.playernum].input(slotstr.c_str()); | |||
| 30170 | std::string inputName = hotbarSlotBindingText(player.playernum, num, binding); | |||
| 30171 | ||||
| 30172 | const unsigned int midpoint = NUM_HOTBAR_SLOTS / 2; | |||
| 30173 | if ( num < midpoint ) | |||
| 30174 | { | |||
| 30175 | pos.x -= (pos.w) * (midpoint - num); | |||
| 30176 | } | |||
| 30177 | else | |||
| 30178 | { | |||
| 30179 | pos.x += (pos.w) * (num - midpoint); | |||
| 30180 | } | |||
| 30181 | ||||
| 30182 | if ( inputName == "" ) | |||
| 30183 | { | |||
| 30184 | slot_text->setText(""); | |||
| 30185 | glyph->disabled = slot->isDisabled(); | |||
| 30186 | glyph->color = 0xFFFFFFFF;// player.shootmode ? 0xFFFFFFFF : makeColor(255, 255, 255, 192); | |||
| 30187 | if ( binding.type == Input::binding_t::KEYBOARD ) | |||
| 30188 | { | |||
| 30189 | glyph->path = Input::inputs[player.playernum].getGlyphPathForBinding(slotstr.c_str(), true); | |||
| 30190 | } | |||
| 30191 | else | |||
| 30192 | { | |||
| 30193 | glyph->path = Input::inputs[player.playernum].getGlyphPathForBinding(slotstr.c_str()); | |||
| 30194 | } | |||
| 30195 | } | |||
| 30196 | else | |||
| 30197 | { | |||
| 30198 | slot_text->setText(inputName.c_str()); | |||
| 30199 | } | |||
| 30200 | ||||
| 30201 | slot->setSize(pos); | |||
| 30202 | ||||
| 30203 | auto glyphImage = Image::get(glyph->path.c_str()); | |||
| 30204 | if ( glyphImage ) | |||
| 30205 | { | |||
| 30206 | glyph->pos.w = std::min((int)glyphImage->getWidth(), slot->getSize().w); | |||
| 30207 | glyph->pos.h = glyphImage->getHeight(); | |||
| 30208 | glyph->pos.x = pos.x + pos.w / 2 - glyph->pos.w / 2; | |||
| 30209 | glyph->pos.y = pos.y - glyph->pos.h; | |||
| 30210 | ||||
| 30211 | if ( binding.type == Input::binding_t::MOUSE_BUTTON ) | |||
| 30212 | { | |||
| 30213 | glyph->pos.y += 4; | |||
| 30214 | } | |||
| 30215 | } | |||
| 30216 | } | |||
| 30217 | ||||
| 30218 | if ( current_hotbar == num ) | |||
| 30219 | { | |||
| 30220 | bool showHighlightedSlot = true; | |||
| 30221 | if ( players[player.playernum]->GUI.activeModule != Player::GUI_t::MODULE_HOTBAR | |||
| 30222 | && player.inventoryUI.frame && !player.inventoryUI.frame->isDisabled() ) | |||
| 30223 | { | |||
| 30224 | // if inventory visible, don't show selection if navigating within inventory | |||
| 30225 | showHighlightedSlot = false; | |||
| 30226 | } | |||
| 30227 | else if ( player.hotbar.useHotbarFaceMenu && inputs.getVirtualMouse(player.playernum)->lastMovementFromController | |||
| 30228 | && player.hotbar.faceMenuButtonHeld == Player::Hotbar_t::FaceMenuGroup::GROUP_NONE | |||
| 30229 | && player.inventoryUI.frame && player.inventoryUI.frame->isDisabled() ) | |||
| 30230 | { | |||
| 30231 | // if inventory invisible, don't show selection if face button not held | |||
| 30232 | showHighlightedSlot = false; | |||
| 30233 | } | |||
| 30234 | ||||
| 30235 | auto highlightSlotItem = highlightSlot->findFrame("hotbar slot item"); | |||
| 30236 | highlightSlotItem->setDisabled(true); | |||
| 30237 | ||||
| 30238 | if ( showHighlightedSlot ) | |||
| 30239 | { | |||
| 30240 | auto slotNumText = slot->findField("slot num text"); | |||
| 30241 | ||||
| 30242 | highlightNumText->setText(slotNumText->getText()); | |||
| 30243 | highlightNumText->setDisabled(slotNumText->isDisabled()); | |||
| 30244 | ||||
| 30245 | highlightSlot->setSize(pos); // this follows the slots around | |||
| 30246 | highlightSlotImg->disabled = false; | |||
| 30247 | updateSlotFrameFromItem(highlightSlotItem, uidToItem(hotbar[num].item)); | |||
| 30248 | ||||
| 30249 | if ( player.inventoryUI.frame ) | |||
| 30250 | { | |||
| 30251 | bool showCursor = true; | |||
| 30252 | if ( !player.shootmode ) | |||
| 30253 | { | |||
| 30254 | if ( inputs.getUIInteraction(player.playernum)->itemMenuOpen && | |||
| 30255 | inputs.getUIInteraction(player.playernum)->itemMenuFromHotbar ) | |||
| 30256 | { | |||
| 30257 | showCursor = true; | |||
| 30258 | } | |||
| 30259 | else if ( inputs.getUIInteraction(player.playernum)->selectedItem | |||
| 30260 | && !highlightSlot->capturesMouseInRealtimeCoords() ) | |||
| 30261 | { | |||
| 30262 | showCursor = false; | |||
| 30263 | } | |||
| 30264 | else if ( !inputs.getUIInteraction(player.playernum)->selectedItem | |||
| 30265 | && !inputs.getVirtualMouse(player.playernum)->lastMovementFromController | |||
| 30266 | && !highlightSlot->capturesMouse() ) | |||
| 30267 | { | |||
| 30268 | showCursor = false; | |||
| 30269 | } | |||
| 30270 | } | |||
| 30271 | else if ( player.shootmode ) | |||
| 30272 | { | |||
| 30273 | showCursor = true; | |||
| 30274 | } | |||
| 30275 | ||||
| 30276 | if ( showCursor ) | |||
| 30277 | { | |||
| 30278 | if ( !player.shootmode ) | |||
| 30279 | { | |||
| 30280 | if ( players[player.playernum]->inventoryUI.selectedItemCursorFrame ) | |||
| 30281 | { | |||
| 30282 | players[player.playernum]->inventoryUI.selectedItemCursorFrame->setDisabled(false); | |||
| 30283 | player.inventoryUI.updateSelectedSlotAnimation(pos.x - 1, pos.y - 1, getSlotSize() - 2, getSlotSize() - 2, | |||
| 30284 | inputs.getVirtualMouse(player.playernum)->draw_cursor); | |||
| 30285 | } | |||
| 30286 | } | |||
| 30287 | else if ( player.shootmode ) | |||
| 30288 | { | |||
| 30289 | if ( shootmodeSelectedSlotCursor ) | |||
| 30290 | { | |||
| 30291 | shootmodeSelectedSlotCursor->setDisabled(false); | |||
| 30292 | bool snapCursor = !inputs.getVirtualMouse(player.playernum)->lastMovementFromController; | |||
| 30293 | if ( useHotbarFaceMenu && faceMenuSnapCursorInstantly ) | |||
| 30294 | { | |||
| 30295 | snapCursor = true; | |||
| 30296 | } | |||
| 30297 | updateSelectedSlotAnimation(pos.x - 1, pos.y - 1, getSlotSize() - 2, getSlotSize() - 2, snapCursor); | |||
| 30298 | } | |||
| 30299 | } | |||
| 30300 | } | |||
| 30301 | else | |||
| 30302 | { | |||
| 30303 | highlightSlotImg->disabled = true; | |||
| 30304 | highlightSlotItem->setDisabled(true); | |||
| 30305 | updateSlotFrameFromItem(slotItem, uidToItem(hotbar[num].item)); | |||
| 30306 | } | |||
| 30307 | } | |||
| 30308 | } | |||
| 30309 | else | |||
| 30310 | { | |||
| 30311 | updateSlotFrameFromItem(slotItem, uidToItem(hotbar[num].item)); | |||
| 30312 | } | |||
| 30313 | } | |||
| 30314 | else | |||
| 30315 | { | |||
| 30316 | updateSlotFrameFromItem(slotItem, uidToItem(hotbar[num].item)); | |||
| 30317 | } | |||
| 30318 | } | |||
| 30319 | } | |||
| 30320 | ||||
| 30321 | bool Player::Hotbar_t::warpMouseToHotbar(const int hotbarSlot, Uint32 flags) | |||
| 30322 | { | |||
| 30323 | if ( !hotbarFrame || hotbarSlot < 0 || hotbarSlot >= NUM_HOTBAR_SLOTS ) | |||
| 30324 | { | |||
| 30325 | return false; | |||
| 30326 | } | |||
| 30327 | if ( auto slotFrame = getHotbarSlotFrame(hotbarSlot) ) | |||
| 30328 | { | |||
| 30329 | slotFrame->warpMouseToFrame(player.playernum, flags); | |||
| 30330 | return true; | |||
| 30331 | } | |||
| 30332 | return false; | |||
| 30333 | } | |||
| 30334 | ||||
| 30335 | Frame* Player::Hotbar_t::getHotbarSlotFrame(const int hotbarSlot) | |||
| 30336 | { | |||
| 30337 | if ( !hotbarFrame || hotbarSlot < 0 || hotbarSlot >= NUM_HOTBAR_SLOTS ) | |||
| 30338 | { | |||
| 30339 | return nullptr; | |||
| 30340 | } | |||
| 30341 | ||||
| 30342 | return hotbarSlotFrames[hotbarSlot]; | |||
| 30343 | } | |||
| 30344 | ||||
| 30345 | static void drawConsoleCommandBuffer() { | |||
| 30346 | if (!command) { | |||
| 30347 | return; | |||
| 30348 | } | |||
| 30349 | int commandPlayer = clientnum; | |||
| 30350 | for ( int i = 0; i < MAXPLAYERS4; ++i ) { | |||
| 30351 | if ( inputs.bPlayerUsingKeyboardControl(i) ) { | |||
| 30352 | commandPlayer = i; | |||
| 30353 | break; | |||
| 30354 | } | |||
| 30355 | } | |||
| 30356 | char buf[1024]; | |||
| 30357 | if ( (ticks - cursorflash) % TICKS_PER_SECOND50 < TICKS_PER_SECOND50 / 2 ) { | |||
| 30358 | snprintf(buf, sizeof(buf), "> %s_", command_str); | |||
| 30359 | } else { | |||
| 30360 | snprintf(buf, sizeof(buf), "> %s", command_str); | |||
| 30361 | } | |||
| 30362 | const char* font; | |||
| 30363 | if (intro) { | |||
| 30364 | font = "fonts/pixelmix.ttf#16#2"; | |||
| 30365 | } else { | |||
| 30366 | if ( players[commandPlayer]->isLocalPlayer() ) | |||
| 30367 | { | |||
| 30368 | font = players[commandPlayer]->messageZone.useBigFont ? | |||
| 30369 | "fonts/pixelmix.ttf#16#2" : "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 30370 | } | |||
| 30371 | else | |||
| 30372 | { | |||
| 30373 | font = "fonts/pixelmix.ttf#16#2"; | |||
| 30374 | } | |||
| 30375 | } | |||
| 30376 | auto text = Text::get(buf, font, 0xffffffff, makeColor(0, 0, 0, 255)); | |||
| 30377 | const int printx = players[commandPlayer]->camera_virtualx1() + 8; | |||
| 30378 | int printy = players[commandPlayer]->camera_virtualy2() - 192; | |||
| 30379 | if ( players[commandPlayer]->messageZone.actualAlignment == Player::MessageZone_t::ALIGN_LEFT_BOTTOM | |||
| 30380 | && players[commandPlayer]->messageZone.chatFrame ) | |||
| 30381 | { | |||
| 30382 | if ( Frame* messageBoxFrame = players[commandPlayer]->messageZone.chatFrame->findFrame("message box") ) | |||
| 30383 | { | |||
| 30384 | printy = messageBoxFrame->getSize().y + messageBoxFrame->getSize().h + 4; | |||
| 30385 | if ( !players[commandPlayer]->messageZone.useBigFont ) | |||
| 30386 | { | |||
| 30387 | printy -= 4; | |||
| 30388 | } | |||
| 30389 | printy += players[commandPlayer]->camera_virtualy1(); | |||
| 30390 | } | |||
| 30391 | } | |||
| 30392 | text->draw(SDL_Rect{0,0,0,0}, SDL_Rect{printx, printy, 0, 0}, | |||
| 30393 | SDL_Rect{0, 0, Frame::virtualScreenX, Frame::virtualScreenY}); | |||
| 30394 | } | |||
| 30395 | ||||
| 30396 | static Uint32 gui_ticks = 0u; | |||
| 30397 | Frame::result_t doFrames() { | |||
| 30398 | Frame::result_t result; | |||
| 30399 | result.usable = false; | |||
| 30400 | result.highlightTime = 0; | |||
| 30401 | result.tooltip = nullptr; | |||
| 30402 | result.removed = false; | |||
| 30403 | if ( gui ) | |||
| 30404 | { | |||
| 30405 | while ( gui_ticks < ticks ) | |||
| 30406 | { | |||
| 30407 | ++gui_ticks; | |||
| 30408 | } | |||
| 30409 | ||||
| 30410 | static ConsoleVariable<bool> gui_process("/gui_process", true); | |||
| 30411 | if (*gui_process) { | |||
| 30412 | result = gui->process(); | |||
| 30413 | } | |||
| 30414 | ||||
| 30415 | static ConsoleVariable<bool> gui_draw("/gui_draw", true); | |||
| 30416 | if (*gui_draw) { | |||
| 30417 | gui->predraw(); | |||
| 30418 | gui->draw(); | |||
| 30419 | if (!movie) { | |||
| 30420 | drawConsoleCommandBuffer(); | |||
| 30421 | } | |||
| 30422 | gui->postdraw(); | |||
| 30423 | } | |||
| 30424 | } | |||
| 30425 | return result; | |||
| 30426 | } | |||
| 30427 | ||||
| 30428 | real_t Player::SkillSheet_t::windowCompactHeightScaleX = 0.0; | |||
| 30429 | real_t Player::SkillSheet_t::windowCompactHeightScaleY = 0.0; | |||
| 30430 | real_t Player::SkillSheet_t::windowHeightScaleX = 0.0; | |||
| 30431 | real_t Player::SkillSheet_t::windowHeightScaleY = 0.0; | |||
| 30432 | bool Player::SkillSheet_t::generateFollowerTableForSkillsheet = false; | |||
| 30433 | SkillSheetFrames_t skillSheetEntryFrames[MAXPLAYERS4]; | |||
| 30434 | ||||
| 30435 | void Player::SkillSheet_t::createSkillSheet() | |||
| 30436 | { | |||
| 30437 | if ( skillFrame ) | |||
| 30438 | { | |||
| 30439 | return; | |||
| 30440 | } | |||
| 30441 | ||||
| 30442 | char name[32]; | |||
| 30443 | snprintf(name, sizeof(name), "player skills %d", player.playernum); | |||
| 30444 | Frame* frame = gameUIFrame[player.playernum]->addFrame(name); | |||
| 30445 | skillFrame = frame; | |||
| 30446 | frame->setSize(SDL_Rect{ players[player.playernum]->camera_virtualx1(), | |||
| 30447 | players[player.playernum]->camera_virtualy1(), | |||
| 30448 | players[player.playernum]->camera_virtualWidth(), | |||
| 30449 | players[player.playernum]->camera_virtualHeight() }); | |||
| 30450 | frame->setHollow(false); | |||
| 30451 | frame->setBorder(0); | |||
| 30452 | frame->setOwner(player.playernum); | |||
| 30453 | frame->setInheritParentFrameOpacity(false); | |||
| 30454 | ||||
| 30455 | auto fade = skillFrame->addImage( | |||
| 30456 | SDL_Rect{ 0, 0, skillFrame->getSize().w, skillFrame->getSize().h }, | |||
| 30457 | 0, "images/system/white.png", "fade img"); | |||
| 30458 | Uint8 r, g, b, a; | |||
| 30459 | getColor(fade->color, &r, &g, &b, &a); | |||
| 30460 | a = 0; | |||
| 30461 | fade->color = makeColor( r, g, b, a); | |||
| 30462 | fade->disabled = true; | |||
| 30463 | ||||
| 30464 | Frame* skillBackground = frame->addFrame("skills frame"); | |||
| 30465 | skillBackground->setHollow(true); | |||
| 30466 | skillSheetEntryFrames[player.playernum].skillsFrame = skillBackground; | |||
| 30467 | const int width = 684; | |||
| 30468 | const int height = 404; | |||
| 30469 | skillBackground->setInheritParentFrameOpacity(false); | |||
| 30470 | skillBackground->setSize(SDL_Rect{ frame->getSize().x, frame->getSize().y, width, height }); | |||
| 30471 | /*auto bgImg = skillBackground->addImage(SDL_Rect{ 0, 0, width, height }, 0xFFFFFFFF, | |||
| 30472 | "*#images/ui/SkillSheet/UI_Skills_Window_02.png", "skills img");*/ | |||
| 30473 | ||||
| 30474 | Frame* allSkillEntriesLeft = skillBackground->addFrame("skill entries frame left"); | |||
| 30475 | allSkillEntriesLeft->setHollow(true); | |||
| 30476 | Frame* allSkillEntriesRight = skillBackground->addFrame("skill entries frame right"); | |||
| 30477 | allSkillEntriesRight->setHollow(true); | |||
| 30478 | skillSheetEntryFrames[player.playernum].entryFrameLeft = allSkillEntriesLeft; | |||
| 30479 | skillSheetEntryFrames[player.playernum].entryFrameRight = allSkillEntriesRight; | |||
| 30480 | //allSkillEntries->setSize(SDL_Rect{ 0, 0, skillBackground->getSize().w, skillBackground->getSize().h }); | |||
| 30481 | ||||
| 30482 | SDL_Rect allSkillEntriesPosLeft{ 0, 0, 182, skillBackground->getSize().h }; | |||
| 30483 | SDL_Rect allSkillEntriesPosRight{ skillBackground->getSize().w - 182, 0, 182, skillBackground->getSize().h }; | |||
| 30484 | allSkillEntriesLeft->setSize(allSkillEntriesPosLeft); | |||
| 30485 | allSkillEntriesRight->setSize(allSkillEntriesPosRight); | |||
| 30486 | ||||
| 30487 | allSkillEntriesLeft->addImage(SDL_Rect{ 0, 12, 182, 376 }, | |||
| 30488 | 0xFFFFFFFF, "*#images/ui/SkillSheet/UI_Skills_Window_Left_04.png", "bg wing left"); | |||
| 30489 | allSkillEntriesLeft->addImage(SDL_Rect{0, 0, 0, 0}, | |||
| 30490 | 0xFFFFFFFF, "*#images/ui/SkillSheet/UI_Skills_Left_Full_00000000.png", "bg wing all skills left"); | |||
| 30491 | allSkillEntriesRight->addImage(SDL_Rect{ 0, 12, 182, 376 }, | |||
| 30492 | 0xFFFFFFFF, "*#images/ui/SkillSheet/UI_Skills_Window_Right_04.png", "bg wing right"); | |||
| 30493 | allSkillEntriesRight->addImage(SDL_Rect{ 0, 0, 0, 0 }, | |||
| 30494 | 0xFFFFFFFF, "*#images/ui/SkillSheet/UI_Skills_Right_Full_00000000.png", "bg wing all skills right"); | |||
| 30495 | ||||
| 30496 | auto skillBackgroundImagesFrame = skillBackground->addFrame("skills bg images"); | |||
| 30497 | skillBackgroundImagesFrame->setHollow(true); | |||
| 30498 | skillSheetEntryFrames[player.playernum].skillBgImgsFrame = skillBackgroundImagesFrame; | |||
| 30499 | skillBackgroundImagesFrame->setSize(SDL_Rect{ 0, 0, skillBackground->getSize().w, skillBackground->getSize().h }); | |||
| 30500 | { | |||
| 30501 | Uint32 color = makeColor(255, 255, 255, 255); | |||
| 30502 | skillBackgroundImagesFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30503 | color, "*#images/ui/SkillSheet/UI_Skills_Window_TL_04.png", skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 30504 | skillBackgroundImagesFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30505 | color, "*#images/ui/SkillSheet/UI_Skills_Window_TR_04.png", skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 30506 | skillBackgroundImagesFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30507 | color, "*#images/ui/SkillSheet/UI_Skills_Window_T_04.png", skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 30508 | skillBackgroundImagesFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30509 | color, "*#images/ui/SkillSheet/UI_Skills_Window_L_03.png", skillsheetEffectBackgroundImages[MIDDLE_LEFT].c_str()); | |||
| 30510 | skillBackgroundImagesFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30511 | color, "*#images/ui/SkillSheet/UI_Skills_Window_R_03.png", skillsheetEffectBackgroundImages[MIDDLE_RIGHT].c_str()); | |||
| 30512 | skillBackgroundImagesFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30513 | makeColor(0, 0, 0, 255), "images/system/white.png", skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 30514 | skillBackgroundImagesFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30515 | color, "*#images/ui/SkillSheet/UI_Skills_Window_BL_03.png", skillsheetEffectBackgroundImages[BOTTOM_LEFT].c_str()); | |||
| 30516 | skillBackgroundImagesFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30517 | color, "*#images/ui/SkillSheet/UI_Skills_Window_BR_03.png", skillsheetEffectBackgroundImages[BOTTOM_RIGHT].c_str()); | |||
| 30518 | skillBackgroundImagesFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30519 | color, "*#images/ui/SkillSheet/UI_Skills_Window_B_03.png", skillsheetEffectBackgroundImages[BOTTOM].c_str()); | |||
| 30520 | imageSetWidthHeight9x9(skillBackgroundImagesFrame, skillsheetEffectBackgroundImages); | |||
| 30521 | ||||
| 30522 | skillBackgroundImagesFrame->addImage(SDL_Rect{ 0, 0, 78, 18 }, | |||
| 30523 | color, "*#images/ui/SkillSheet/UI_Skills_Window_Flourish_T.png", "flourish top"); | |||
| 30524 | skillBackgroundImagesFrame->addImage(SDL_Rect{ 0, 0, 34, 14 }, | |||
| 30525 | color, "*#images/ui/SkillSheet/UI_Skills_Window_Flourish_B.png", "flourish bottom"); | |||
| 30526 | } | |||
| 30527 | ||||
| 30528 | const int skillEntryStartY = 38; | |||
| 30529 | SDL_Rect skillEntryPos{ 0, skillEntryStartY, 182, 40 }; | |||
| 30530 | SDL_Rect skillSelectorPos{ 0, 2, 146, 32 }; | |||
| 30531 | const char* boldFont = "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 30532 | const char* numberFont = "fonts/pixelmix.ttf#16"; | |||
| 30533 | //const char* titleFont = "fonts/pixel_maz_multiline.ttf#24#2"; | |||
| 30534 | const char* titleFont = "fonts/pixelmix.ttf#24#2"; | |||
| 30535 | const char* descFont = "fonts/pixel_maz_multiline.ttf#16#2"; | |||
| 30536 | for ( int i = 0; i < 8; ++i ) | |||
| 30537 | { | |||
| 30538 | char skillname[32]; | |||
| 30539 | snprintf(skillname, sizeof(skillname), "skill %d", i); | |||
| 30540 | Frame* entry = allSkillEntriesRight->addFrame(skillname); | |||
| 30541 | entry->setHollow(true); | |||
| 30542 | skillSheetEntryFrames[player.playernum].entryFrames[i] = entry; | |||
| 30543 | entry->setSize(skillEntryPos); | |||
| 30544 | auto selector = entry->addImage(skillSelectorPos, 0xFFFFFFFF, "*#images/ui/SkillSheet/UI_Skills_SkillSelector_00.png", "selector img"); | |||
| 30545 | SDL_Rect imgBgPos{ skillEntryPos.w - 36, 0, 36, 36 }; | |||
| 30546 | entry->addImage(imgBgPos, 0xFFFFFFFF, "*#images/ui/SkillSheet/UI_Skills_Icons_BG00_00.png", "skill icon bg"); | |||
| 30547 | SDL_Rect imgFgPos{ imgBgPos.x + 6, imgBgPos.y + 6, 24, 24 }; | |||
| 30548 | entry->addImage(imgFgPos, 0xFFFFFFFF, "", "skill icon fg"); | |||
| 30549 | SDL_Rect statPos{ 10, 6, 24, 24 }; | |||
| 30550 | auto statIcon = entry->addImage(statPos, 0xFFFFFFFF, "", "stat icon"); | |||
| 30551 | if ( i < skillSheetData.skillEntries.size() ) | |||
| 30552 | { | |||
| 30553 | statIcon->path = skillSheetData.skillEntries[i].statIconPath; | |||
| 30554 | } | |||
| 30555 | skillEntryPos.y += skillEntryPos.h; | |||
| 30556 | ||||
| 30557 | SDL_Rect profNamePos{ statPos.x + statPos.w - 32, 4, 98, 28 }; | |||
| 30558 | Field* profName = entry->addField("skill name", 64); | |||
| 30559 | profName->setSize(profNamePos); | |||
| 30560 | profName->setHJustify(Field::justify_t::RIGHT); | |||
| 30561 | profName->setVJustify(Field::justify_t::CENTER); | |||
| 30562 | profName->setFont(boldFont); | |||
| 30563 | profName->setTextColor(skillSheetData.defaultTextColor); | |||
| 30564 | if ( i < skillSheetData.skillEntries.size() ) | |||
| 30565 | { | |||
| 30566 | profName->setText(skillSheetData.skillEntries[i].name.c_str()); | |||
| 30567 | } | |||
| 30568 | else | |||
| 30569 | { | |||
| 30570 | profName->setText("Default"); | |||
| 30571 | } | |||
| 30572 | ||||
| 30573 | SDL_Rect profLevelPos{ profNamePos.x + profNamePos.w + 8 - 2, profNamePos.y, 34, 28 }; | |||
| 30574 | Field* profLevel = entry->addField("skill level", 16); | |||
| 30575 | profLevel->setSize(profLevelPos); | |||
| 30576 | profLevel->setHJustify(Field::justify_t::RIGHT); | |||
| 30577 | profLevel->setVJustify(Field::justify_t::CENTER); | |||
| 30578 | profLevel->setFont(numberFont); | |||
| 30579 | profLevel->setTextColor(skillSheetData.defaultTextColor); | |||
| 30580 | profLevel->setText("0"); | |||
| 30581 | } | |||
| 30582 | ||||
| 30583 | skillEntryPos.x = 0; | |||
| 30584 | skillEntryPos.y = skillEntryStartY; | |||
| 30585 | skillSelectorPos.x = 36; | |||
| 30586 | ||||
| 30587 | for ( int i = 8; i < 16; ++i ) | |||
| 30588 | { | |||
| 30589 | char skillname[32]; | |||
| 30590 | snprintf(skillname, sizeof(skillname), "skill %d", i); | |||
| 30591 | Frame* entry = allSkillEntriesLeft->addFrame(skillname); | |||
| 30592 | entry->setHollow(true); | |||
| 30593 | skillSheetEntryFrames[player.playernum].entryFrames[i] = entry; | |||
| 30594 | entry->setSize(skillEntryPos); | |||
| 30595 | auto selector = entry->addImage(skillSelectorPos, 0xFFFFFFFF, "*#images/ui/SkillSheet/UI_Skills_SkillSelectorR_00.png", "selector img"); | |||
| 30596 | SDL_Rect imgBgPos{ 0, 0, 36, 36 }; | |||
| 30597 | entry->addImage(imgBgPos, 0xFFFFFFFF, "*#images/ui/SkillSheet/UI_Skills_Icons_BG00_00.png", "skill icon bg"); | |||
| 30598 | SDL_Rect imgFgPos{ imgBgPos.x + 6, imgBgPos.y + 6, 24, 24 }; | |||
| 30599 | entry->addImage(imgFgPos, 0xFFFFFFFF, "*#images/ui/SkillSheet/icons/Alchemy01.png", "skill icon fg"); | |||
| 30600 | SDL_Rect statPos{ skillEntryPos.w - 10 - 24, 6, 24, 24 }; | |||
| 30601 | auto statIcon = entry->addImage(statPos, 0xFFFFFFFF, "", "stat icon"); | |||
| 30602 | if ( i < skillSheetData.skillEntries.size() ) | |||
| 30603 | { | |||
| 30604 | statIcon->path = skillSheetData.skillEntries[i].statIconPath; | |||
| 30605 | } | |||
| 30606 | skillEntryPos.y += skillEntryPos.h; | |||
| 30607 | ||||
| 30608 | SDL_Rect profNamePos{ statPos.x - 98 + 32, 4, 98, 28 }; | |||
| 30609 | Field* profName = entry->addField("skill name", 64); | |||
| 30610 | profName->setSize(profNamePos); | |||
| 30611 | profName->setHJustify(Field::justify_t::LEFT); | |||
| 30612 | profName->setVJustify(Field::justify_t::CENTER); | |||
| 30613 | profName->setFont(boldFont); | |||
| 30614 | profName->setTextColor(skillSheetData.defaultTextColor); | |||
| 30615 | if ( i < skillSheetData.skillEntries.size() ) | |||
| 30616 | { | |||
| 30617 | profName->setText(skillSheetData.skillEntries[i].name.c_str()); | |||
| 30618 | } | |||
| 30619 | else | |||
| 30620 | { | |||
| 30621 | profName->setText("Default"); | |||
| 30622 | } | |||
| 30623 | ||||
| 30624 | SDL_Rect profLevelPos{ profNamePos.x - 12 - 32, profNamePos.y, 34, 28 }; | |||
| 30625 | Field* profLevel = entry->addField("skill level", 16); | |||
| 30626 | profLevel->setSize(profLevelPos); | |||
| 30627 | profLevel->setHJustify(Field::justify_t::RIGHT); | |||
| 30628 | profLevel->setVJustify(Field::justify_t::CENTER); | |||
| 30629 | profLevel->setFont(numberFont); | |||
| 30630 | profLevel->setTextColor(skillSheetData.defaultTextColor); | |||
| 30631 | profLevel->setText("0"); | |||
| 30632 | } | |||
| 30633 | ||||
| 30634 | SDL_Rect skillTitlePos{ skillBackground->getSize().w / 2 - 320 / 2, 14, 320, 40 }; | |||
| 30635 | auto skillTitleTxt = skillBackground->addField("skill title txt", 64); | |||
| 30636 | skillTitleTxt->setHJustify(Field::justify_t::CENTER); | |||
| 30637 | skillTitleTxt->setVJustify(Field::justify_t::CENTER); | |||
| 30638 | skillTitleTxt->setText(""); | |||
| 30639 | skillTitleTxt->setSize(skillTitlePos); | |||
| 30640 | skillTitleTxt->setFont(titleFont); | |||
| 30641 | skillTitleTxt->setOntop(true); | |||
| 30642 | skillTitleTxt->setTextColor(makeColor(201, 162, 100, 255)); | |||
| 30643 | ||||
| 30644 | { | |||
| 30645 | auto closeBtn = skillBackground->addButton("close skills button"); | |||
| 30646 | SDL_Rect closeBtnPos; | |||
| 30647 | closeBtnPos.x = skillBackground->getSize().w - 66; | |||
| 30648 | closeBtnPos.y = 22; | |||
| 30649 | closeBtnPos.w = 26; | |||
| 30650 | closeBtnPos.h = 26; | |||
| 30651 | closeBtn->setSize(closeBtnPos); | |||
| 30652 | closeBtn->setColor(makeColor(255, 255, 255, 255)); | |||
| 30653 | closeBtn->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 30654 | closeBtn->setTextHighlightColor(makeColor(201, 162, 100, 255)); | |||
| 30655 | closeBtn->setText("X"); | |||
| 30656 | closeBtn->setOntop(true); | |||
| 30657 | closeBtn->setFont(boldFont); | |||
| 30658 | closeBtn->setHideGlyphs(true); | |||
| 30659 | closeBtn->setHideKeyboardGlyphs(true); | |||
| 30660 | closeBtn->setHideSelectors(true); | |||
| 30661 | closeBtn->setMenuConfirmControlType(0); | |||
| 30662 | closeBtn->setBackground("*#images/ui/Skillsheet/Button_X_00.png"); | |||
| 30663 | closeBtn->setBackgroundHighlighted("*#images/ui/Skillsheet/Button_XHigh_00.png"); | |||
| 30664 | closeBtn->setBackgroundActivated("*#images/ui/Skillsheet/Button_XPress_00.png"); | |||
| 30665 | closeBtn->setCallback([](Button& button) { | |||
| 30666 | players[button.getOwner()]->skillSheet.closeSkillSheet(); | |||
| 30667 | Player::soundCancel(); | |||
| 30668 | }); | |||
| 30669 | closeBtn->setTickCallback([](Widget& widget) { | |||
| 30670 | if ( widget.isSelected() ) | |||
| 30671 | { | |||
| 30672 | if ( !inputs.getVirtualMouse(widget.getOwner())->draw_cursor ) | |||
| 30673 | { | |||
| 30674 | widget.deselect(); | |||
| 30675 | } | |||
| 30676 | } | |||
| 30677 | }); | |||
| 30678 | } | |||
| 30679 | ||||
| 30680 | SDL_Rect descPos{ 0, 54, 320, 324 }; | |||
| 30681 | descPos.x = skillBackground->getSize().w / 2 - descPos.w / 2; | |||
| 30682 | auto skillDescriptionFrame = skillBackground->addFrame("skill desc frame"); | |||
| 30683 | skillDescriptionFrame->setHollow(true); | |||
| 30684 | skillSheetEntryFrames[player.playernum].skillDescFrame = skillDescriptionFrame; | |||
| 30685 | skillDescriptionFrame->setSize(descPos); | |||
| 30686 | ||||
| 30687 | /*auto debugRect = skillDescriptionFrame->addImage(SDL_Rect{ 0, 0, descPos.w, descPos.h }, 0xFFFFFFFF, | |||
| 30688 | "images/system/white.png", "")*/; | |||
| 30689 | ||||
| 30690 | auto slider = skillDescriptionFrame->addSlider("skill slider"); | |||
| 30691 | slider->setBorder(24); | |||
| 30692 | slider->setMinValue(0); | |||
| 30693 | slider->setMaxValue(100); | |||
| 30694 | slider->setValue(0); | |||
| 30695 | SDL_Rect sliderPos{ descPos.w - 34, 4, 30, descPos.h - 8 }; | |||
| 30696 | slider->setRailSize(sliderPos); | |||
| 30697 | slider->setHandleSize(SDL_Rect{ 0, 0, 34, 34 }); | |||
| 30698 | slider->setOrientation(Slider::SLIDER_VERTICAL); | |||
| 30699 | //slider->setCallback(callback); | |||
| 30700 | slider->setColor(makeColor(255, 255, 255, 255)); | |||
| 30701 | slider->setHighlightColor(makeColor(255, 255, 255, 255)); | |||
| 30702 | slider->setHandleImage("*#images/ui/Main Menus/Settings/Settings_Slider_Boulder00.png"); | |||
| 30703 | slider->setRailImage("*#images/ui/Main Menus/Settings/Settings_Slider_Backing00.png"); | |||
| 30704 | slider->setHideGlyphs(true); | |||
| 30705 | slider->setHideKeyboardGlyphs(true); | |||
| 30706 | slider->setHideSelectors(true); | |||
| 30707 | slider->setMenuConfirmControlType(0); | |||
| 30708 | ||||
| 30709 | Font* actualFont = Font::get(descFont); | |||
| 30710 | int fontHeight; | |||
| 30711 | actualFont->sizeText("_", nullptr, &fontHeight); | |||
| 30712 | ||||
| 30713 | auto scrollAreaOuterFrame = skillDescriptionFrame->addFrame("scroll area outer frame"); | |||
| 30714 | scrollAreaOuterFrame->setHollow(true); | |||
| 30715 | skillSheetEntryFrames[player.playernum].scrollAreaOuterFrame = scrollAreaOuterFrame; | |||
| 30716 | scrollAreaOuterFrame->setSize(SDL_Rect{ 16, 4, sliderPos.x - 4 - 16, descPos.h - 8 }); | |||
| 30717 | auto scrollAreaFrame = scrollAreaOuterFrame->addFrame("skill scroll area"); | |||
| 30718 | scrollAreaFrame->setHollow(true); | |||
| 30719 | skillSheetEntryFrames[player.playernum].scrollArea = scrollAreaFrame; | |||
| 30720 | scrollAreaFrame->setSize(SDL_Rect{ 0, 0, scrollAreaOuterFrame->getSize().w, 1000 }); | |||
| 30721 | ||||
| 30722 | SDL_Rect txtPos{ 0, 0, scrollAreaFrame->getSize().w, scrollAreaFrame->getSize().h }; | |||
| 30723 | { | |||
| 30724 | auto skillLvlHeaderTxt = scrollAreaFrame->addField("skill lvl header txt", 128); | |||
| 30725 | skillLvlHeaderTxt->setFont(descFont); | |||
| 30726 | skillLvlHeaderTxt->setSize(txtPos); | |||
| 30727 | skillLvlHeaderTxt->setText(Language::get(5961)); | |||
| 30728 | ||||
| 30729 | auto skillLvlHeaderVal = scrollAreaFrame->addField("skill lvl header val", 128); | |||
| 30730 | skillLvlHeaderVal->setFont(descFont); | |||
| 30731 | skillLvlHeaderVal->setSize(txtPos); | |||
| 30732 | skillLvlHeaderVal->setText(""); | |||
| 30733 | skillLvlHeaderVal->setHJustify(Field::justify_t::RIGHT); | |||
| 30734 | ||||
| 30735 | txtPos.y += fontHeight; | |||
| 30736 | } | |||
| 30737 | { | |||
| 30738 | const int iconSize = 24; | |||
| 30739 | auto statIcon = scrollAreaFrame->addImage( | |||
| 30740 | SDL_Rect{ txtPos.x + txtPos.w - iconSize, txtPos.y, iconSize, iconSize }, | |||
| 30741 | 0xFFFFFFFF, "*#images/ui/CharSheet/HUD_CharSheet_DEX_00.png", "stat icon"); | |||
| 30742 | ||||
| 30743 | txtPos.y += std::max(0, iconSize - fontHeight); | |||
| 30744 | auto statHeaderTxt = scrollAreaFrame->addField("stat header txt", 128); | |||
| 30745 | statHeaderTxt->setFont(descFont); | |||
| 30746 | statHeaderTxt->setSize(txtPos); | |||
| 30747 | statHeaderTxt->setText(Language::get(5962)); | |||
| 30748 | ||||
| 30749 | auto statTypeTxt = scrollAreaFrame->addField("stat type txt", 128); | |||
| 30750 | statTypeTxt->setFont(descFont); | |||
| 30751 | txtPos.w -= iconSize + 4; | |||
| 30752 | statTypeTxt->setSize(txtPos); | |||
| 30753 | txtPos.w += iconSize + 4; | |||
| 30754 | statTypeTxt->setText(""); | |||
| 30755 | statTypeTxt->setHJustify(Field::justify_t::RIGHT); | |||
| 30756 | txtPos.y += fontHeight; | |||
| 30757 | txtPos.y += fontHeight / 2; | |||
| 30758 | } | |||
| 30759 | { | |||
| 30760 | auto skillDescriptionTxt = scrollAreaFrame->addField("skill desc txt", 1024); | |||
| 30761 | skillDescriptionTxt->setFont(descFont); | |||
| 30762 | skillDescriptionTxt->setSize(txtPos); | |||
| 30763 | skillDescriptionTxt->setText(""); | |||
| 30764 | //skillDescriptionTxt->setTextColor(makeColor(201, 162, 100, 255)); | |||
| 30765 | skillDescriptionTxt->setHJustify(Field::justify_t::CENTER); | |||
| 30766 | skillDescriptionTxt->setOntop(true); | |||
| 30767 | ||||
| 30768 | auto skillDescriptionBgFrame = scrollAreaFrame->addFrame("skill desc bg frame"); | |||
| 30769 | skillDescriptionBgFrame->setHollow(true); | |||
| 30770 | { | |||
| 30771 | //Uint32 color = makeColor(22, 24, 29, 255); | |||
| 30772 | Uint32 color = makeColor(255, 255, 255, 128); | |||
| 30773 | skillDescriptionBgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30774 | color, "*#images/ui/SkillSheet/UI_Skills_LegendBox_TL_00.png", skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 30775 | skillDescriptionBgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30776 | color, "*#images/ui/SkillSheet/UI_Skills_LegendBox_TR_00.png", skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 30777 | skillDescriptionBgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30778 | color, "*#images/ui/SkillSheet/UI_Skills_LegendBox_T_00.png", skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 30779 | skillDescriptionBgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30780 | color, "*#images/ui/SkillSheet/UI_Skills_LegendBox_ML_00.png", skillsheetEffectBackgroundImages[MIDDLE_LEFT].c_str()); | |||
| 30781 | skillDescriptionBgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30782 | color, "*#images/ui/SkillSheet/UI_Skills_LegendBox_MR_00.png", skillsheetEffectBackgroundImages[MIDDLE_RIGHT].c_str()); | |||
| 30783 | skillDescriptionBgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30784 | color, "*#images/ui/SkillSheet/UI_Skills_LegendBox_M_00.png", skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 30785 | skillDescriptionBgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30786 | color, "*#images/ui/SkillSheet/UI_Skills_LegendBox_BL_00.png", skillsheetEffectBackgroundImages[BOTTOM_LEFT].c_str()); | |||
| 30787 | skillDescriptionBgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30788 | color, "*#images/ui/SkillSheet/UI_Skills_LegendBox_BR_00.png", skillsheetEffectBackgroundImages[BOTTOM_RIGHT].c_str()); | |||
| 30789 | skillDescriptionBgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30790 | color, "*#images/ui/SkillSheet/UI_Skills_LegendBox_B_00.png", skillsheetEffectBackgroundImages[BOTTOM].c_str()); | |||
| 30791 | imageSetWidthHeight9x9(skillDescriptionBgFrame, skillsheetEffectBackgroundImages); | |||
| 30792 | } | |||
| 30793 | ||||
| 30794 | ||||
| 30795 | int txtHeight = skillDescriptionTxt->getNumTextLines() * actualFont->height(true); | |||
| 30796 | ||||
| 30797 | txtPos.y += txtHeight; | |||
| 30798 | txtPos.y += fontHeight / 2; | |||
| 30799 | ||||
| 30800 | } | |||
| 30801 | { | |||
| 30802 | char effectFrameName[64] = ""; | |||
| 30803 | char effectFieldName[64] = ""; | |||
| 30804 | char effectFieldVal[64] = ""; | |||
| 30805 | char effectBgName[64]; | |||
| 30806 | int effectXOffset = 72; // tmp paramters - configured in skillsheet json | |||
| 30807 | int effectBackgroundXOffset = 8; | |||
| 30808 | int effectBackgroundWidth = 80; | |||
| 30809 | auto effectLargeBgImg = scrollAreaFrame->addImage( | |||
| 30810 | SDL_Rect{ 0, 0, 0, 0 }, | |||
| 30811 | makeColor(10, 4, 4, 255), "images/system/white.png", "effect frame bg tmp"); | |||
| 30812 | effectLargeBgImg->disabled = true; | |||
| 30813 | for ( int i = 0; i < 10; ++i ) | |||
| 30814 | { | |||
| 30815 | snprintf(effectFrameName, sizeof(effectFrameName), "effect %d frame", i); | |||
| 30816 | auto effectFrame = scrollAreaFrame->addFrame(effectFrameName); | |||
| 30817 | effectFrame->setHollow(true); | |||
| 30818 | skillSheetEntryFrames[player.playernum].effectFrames[i] = effectFrame; | |||
| 30819 | effectFrame->setSize(SDL_Rect{ txtPos.x, txtPos.y - 2, txtPos.w, fontHeight + 8 }); | |||
| 30820 | effectFrame->addImage( | |||
| 30821 | SDL_Rect{ 0, 0, effectFrame->getSize().w, effectFrame->getSize().h - 4 }, | |||
| 30822 | makeColor(91, 73, 57, 255), "images/system/white.png", "effect frame bg highlight"); | |||
| 30823 | int valueX = effectFrame->getSize().w - effectXOffset; | |||
| 30824 | ||||
| 30825 | auto valBgImgFrame = effectFrame->addFrame("effect val bg frame"); | |||
| 30826 | valBgImgFrame->setHollow(true); | |||
| 30827 | valBgImgFrame->setSize(SDL_Rect{ valueX - effectBackgroundXOffset, 0, effectBackgroundWidth, effectFrame->getSize().h - 4}); | |||
| 30828 | { | |||
| 30829 | Uint32 color = makeColor(51, 33, 26, 255); | |||
| 30830 | valBgImgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30831 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_TL00.png", skillsheetEffectBackgroundImages[TOP_LEFT].c_str()); | |||
| 30832 | valBgImgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30833 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_TR00.png", skillsheetEffectBackgroundImages[TOP_RIGHT].c_str()); | |||
| 30834 | valBgImgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30835 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_T00.png", skillsheetEffectBackgroundImages[TOP].c_str()); | |||
| 30836 | valBgImgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30837 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_L00.png", skillsheetEffectBackgroundImages[MIDDLE_LEFT].c_str()); | |||
| 30838 | valBgImgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30839 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_R00.png", skillsheetEffectBackgroundImages[MIDDLE_RIGHT].c_str()); | |||
| 30840 | valBgImgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30841 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_M00.png", skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 30842 | valBgImgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30843 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_BL00.png", skillsheetEffectBackgroundImages[BOTTOM_LEFT].c_str()); | |||
| 30844 | valBgImgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30845 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_BR00.png", skillsheetEffectBackgroundImages[BOTTOM_RIGHT].c_str()); | |||
| 30846 | valBgImgFrame->addImage(SDL_Rect{ 0, 0, 6, 6 }, | |||
| 30847 | color, "*#images/ui/SkillSheet/UI_Skills_EffectBG_B00.png", skillsheetEffectBackgroundImages[BOTTOM].c_str()); | |||
| 30848 | ||||
| 30849 | /*valBgImgFrame->addImage( | |||
| 30850 | SDL_Rect{ 0, 0, effectFrame->getSize().w, effectFrame->getSize().h - 4 }, | |||
| 30851 | makeColor(255, 255, 255, 128), "images/system/white.png", "tmp tmp");*/ | |||
| 30852 | imageSetWidthHeight9x9(valBgImgFrame, skillsheetEffectBackgroundImages); | |||
| 30853 | } | |||
| 30854 | ||||
| 30855 | auto effectTxtFrame = effectFrame->addFrame("effect txt frame"); | |||
| 30856 | effectTxtFrame->setHollow(true); | |||
| 30857 | effectTxtFrame->setSize(SDL_Rect{ 0, 0, effectFrame->getSize().w - effectXOffset - effectBackgroundXOffset, effectFrame->getSize().h - 4 }); | |||
| 30858 | auto effectTxt = effectTxtFrame->addField("effect txt", 1024); | |||
| 30859 | effectTxt->setFont(descFont); | |||
| 30860 | effectTxt->setSize(SDL_Rect{0, 0, 1000, effectTxtFrame->getSize().h}); // large 1000px to handle large text length marquee | |||
| 30861 | effectTxt->setVJustify(Field::justify_t::CENTER); | |||
| 30862 | effectTxt->setText(""); | |||
| 30863 | effectTxt->setTextColor(makeColor(201, 162, 100, 255)); | |||
| 30864 | ||||
| 30865 | auto effectValFrame = effectFrame->addFrame("effect val frame"); | |||
| 30866 | effectValFrame->setHollow(true); | |||
| 30867 | effectValFrame->setSize(SDL_Rect{ valueX, 0, effectXOffset, effectFrame->getSize().h - 4 }); | |||
| 30868 | auto effectVal = effectValFrame->addField("effect val", 1024); | |||
| 30869 | effectVal->setFont(descFont); | |||
| 30870 | effectVal->setSize(SDL_Rect{ 0, 0, 1000, effectValFrame->getSize().h }); // large 1000px to handle large text length marquee | |||
| 30871 | effectVal->setVJustify(Field::justify_t::CENTER); | |||
| 30872 | effectVal->setText(""); | |||
| 30873 | effectVal->setTextColor(makeColor(201, 162, 100, 255)); | |||
| 30874 | ||||
| 30875 | //effectFrame->setDisabled(true); | |||
| 30876 | ||||
| 30877 | txtPos.y += effectFrame->getSize().h; | |||
| 30878 | } | |||
| 30879 | } | |||
| 30880 | { | |||
| 30881 | auto legendDivImg = scrollAreaFrame->addImage(SDL_Rect{ 0, txtPos.y, 212, 28 }, 0xFFFFFFFF, | |||
| 30882 | "*#images/ui/SkillSheet/UI_Skills_Separator_00.png", "legend div"); | |||
| 30883 | legendDivImg->pos.x = scrollAreaFrame->getSize().w / 2 - legendDivImg->pos.w / 2; | |||
| 30884 | auto legendDivTxt = scrollAreaFrame->addField("legend div text", 128); | |||
| 30885 | legendDivTxt->setText(Language::get(4056)); | |||
| 30886 | SDL_Rect legendDivTxtPos = legendDivImg->pos; | |||
| 30887 | legendDivTxt->setSize(legendDivTxtPos); | |||
| 30888 | legendDivTxt->setFont(descFont); | |||
| 30889 | legendDivTxt->setHJustify(Field::justify_t::CENTER); | |||
| 30890 | ||||
| 30891 | auto legendFrame = scrollAreaFrame->addFrame("legend frame"); | |||
| 30892 | legendFrame->setHollow(true); | |||
| 30893 | skillSheetEntryFrames[player.playernum].legendFrame = legendFrame; | |||
| 30894 | SDL_Rect legendPos{ 0, txtPos.y, txtPos.w, 100 }; | |||
| 30895 | legendFrame->setSize(legendPos); | |||
| 30896 | auto tl = legendFrame->addImage(SDL_Rect{ 0, 0, 18, 18 }, 0xFFFFFFFF, | |||
| 30897 | "*#images/ui/SkillSheet/UI_Skills_LegendBox_TL_00.png", "top left img"); | |||
| 30898 | auto tm = legendFrame->addImage(SDL_Rect{ 18, 0, legendPos.w - 18 * 2, 18 }, 0xFFFFFFFF, | |||
| 30899 | "*#images/ui/SkillSheet/UI_Skills_LegendBox_T_00.png", "top img"); | |||
| 30900 | auto tr = legendFrame->addImage(SDL_Rect{ legendPos.w - 18, 0, 18, 18 }, 0xFFFFFFFF, | |||
| 30901 | "*#images/ui/SkillSheet/UI_Skills_LegendBox_TR_00.png", "top right img"); | |||
| 30902 | ||||
| 30903 | auto ml = legendFrame->addImage(SDL_Rect{ 0, 18, 18, legendPos.h - 18 * 2 }, 0xFFFFFFFF, | |||
| 30904 | "*#images/ui/SkillSheet/UI_Skills_LegendBox_ML_00.png", "middle left img"); | |||
| 30905 | auto mm = legendFrame->addImage(SDL_Rect{ 18, 18, legendPos.w - 18 * 2, ml->pos.h }, 0xFFFFFFFF, | |||
| 30906 | "*#images/ui/SkillSheet/UI_Skills_LegendBox_M_00.png", "middle img"); | |||
| 30907 | auto mr = legendFrame->addImage(SDL_Rect{ legendPos.w - 18, 18, 18, ml->pos.h }, 0xFFFFFFFF, | |||
| 30908 | "*#images/ui/SkillSheet/UI_Skills_LegendBox_MR_00.png", "middle right img"); | |||
| 30909 | ||||
| 30910 | auto bl = legendFrame->addImage(SDL_Rect{ 0, ml->pos.y + ml->pos.h, 18, 18 }, 0xFFFFFFFF, | |||
| 30911 | "*#images/ui/SkillSheet/UI_Skills_LegendBox_BL_00.png", "bottom left img"); | |||
| 30912 | auto bm = legendFrame->addImage(SDL_Rect{ 18, bl->pos.y, legendPos.w - 18 * 2, 18 }, 0xFFFFFFFF, | |||
| 30913 | "*#images/ui/SkillSheet/UI_Skills_LegendBox_B_00.png", "bottom img"); | |||
| 30914 | auto br = legendFrame->addImage(SDL_Rect{ legendPos.w - 18, bl->pos.y, 18, 18 }, 0xFFFFFFFF, | |||
| 30915 | "*#images/ui/SkillSheet/UI_Skills_LegendBox_BR_00.png", "bottom right img"); | |||
| 30916 | ||||
| 30917 | auto backerImg = scrollAreaFrame->addImage(SDL_Rect{ 0, 0, 154, 12 }, 0xFFFFFFFF, | |||
| 30918 | "*#images/ui/SkillSheet/UI_Skills_LegendTextBacker_00.png", "legend txt backer img"); | |||
| 30919 | backerImg->disabled = true; | |||
| 30920 | ||||
| 30921 | auto legendText = legendFrame->addField("legend text", 256); | |||
| 30922 | legendText->setText(""); | |||
| 30923 | legendText->setSize(mm->pos); | |||
| 30924 | legendText->setFont(descFont); | |||
| 30925 | legendText->setHJustify(Field::justify_t::CENTER); | |||
| 30926 | ||||
| 30927 | skillBackground->setBlitChildren(true); | |||
| 30928 | } | |||
| 30929 | ||||
| 30930 | std::string promptFont = "fonts/pixel_maz.ttf#32#2"; | |||
| 30931 | const int promptWidth = 60; | |||
| 30932 | const int promptHeight = 27; | |||
| 30933 | auto promptBack = frame->addField("prompt back txt", 16); | |||
| 30934 | promptBack->setSize(SDL_Rect{ frame->getSize().w - promptWidth - 16, // lower right corner | |||
| 30935 | 0, promptWidth, promptHeight }); | |||
| 30936 | promptBack->setFont(promptFont.c_str()); | |||
| 30937 | promptBack->setHJustify(Field::justify_t::RIGHT); | |||
| 30938 | promptBack->setVJustify(Field::justify_t::CENTER); | |||
| 30939 | promptBack->setText(Language::get(4053)); | |||
| 30940 | //promptBack->setOntop(true); | |||
| 30941 | promptBack->setTextColor(makeColor(201, 162, 100, 255)); | |||
| 30942 | ||||
| 30943 | auto promptBackImg = frame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, | |||
| 30944 | "", "prompt back img"); | |||
| 30945 | promptBackImg->disabled = true; | |||
| 30946 | //promptBackImg->ontop = true; | |||
| 30947 | ||||
| 30948 | auto promptScroll = frame->addField("prompt scroll txt", 16); | |||
| 30949 | promptScroll->setSize(SDL_Rect{ frame->getSize().w - promptWidth - 16, // lower right corner | |||
| 30950 | 0, promptWidth, promptHeight }); | |||
| 30951 | promptScroll->setFont(promptFont.c_str()); | |||
| 30952 | promptScroll->setHJustify(Field::justify_t::LEFT); | |||
| 30953 | promptScroll->setVJustify(Field::justify_t::CENTER); | |||
| 30954 | promptScroll->setText(Language::get(4062)); | |||
| 30955 | //promptScroll->setOntop(true); | |||
| 30956 | promptScroll->setTextColor(makeColor(201, 162, 100, 255)); | |||
| 30957 | ||||
| 30958 | auto promptScrollImg = frame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, | |||
| 30959 | "", "prompt scroll img"); | |||
| 30960 | promptScrollImg->disabled = true; | |||
| 30961 | promptScrollImg->ontop = true; | |||
| 30962 | } | |||
| 30963 | ||||
| 30964 | struct SkillSheetCache_t | |||
| 30965 | { | |||
| 30966 | int proficiencyLevelCached; | |||
| 30967 | int highlightedSkill = -2; | |||
| 30968 | int selectedSkill = -2; | |||
| 30969 | }; | |||
| 30970 | SkillSheetCache_t skillsheetCache[MAXPLAYERS4][NUMPROFICIENCIES]; | |||
| 30971 | ||||
| 30972 | void Player::SkillSheet_t::resetSkillDisplay() | |||
| 30973 | { | |||
| 30974 | bSkillSheetEntryLoaded = false; | |||
| 30975 | scrollInertia = 0.0; | |||
| 30976 | for ( int i = 0; i < NUMPROFICIENCIES; ++i ) | |||
| 30977 | { | |||
| 30978 | skillsheetCache[player.playernum][i].proficiencyLevelCached = -1; | |||
| 30979 | skillsheetCache[player.playernum][i].highlightedSkill = -2; | |||
| 30980 | skillsheetCache[player.playernum][i].selectedSkill = -2; | |||
| 30981 | } | |||
| 30982 | ||||
| 30983 | for ( auto& skillEntry : skillSheetData.skillEntries ) | |||
| 30984 | { | |||
| 30985 | for ( auto& skillEffect : skillEntry.effects ) | |||
| 30986 | { | |||
| 30987 | skillEffect.marqueeTicks[player.playernum] = 0; | |||
| 30988 | skillEffect.marquee[player.playernum] = 0.0; | |||
| 30989 | skillEffect.marqueeCompleted[player.playernum] = false; | |||
| 30990 | skillEffect.effectUpdatedAtSkillLevel = -1; | |||
| 30991 | skillEffect.cachedWidth = -1; | |||
| 30992 | skillEffect.effectUpdatedAtMonsterType = -1; | |||
| 30993 | } | |||
| 30994 | } | |||
| 30995 | } | |||
| 30996 | ||||
| 30997 | void Player::SkillSheet_t::closeSkillSheet() | |||
| 30998 | { | |||
| 30999 | bSkillSheetOpen = false; | |||
| 31000 | if ( skillFrame ) | |||
| 31001 | { | |||
| 31002 | skillFrame->setDisabled(true); | |||
| 31003 | } | |||
| 31004 | resetSkillDisplay(); | |||
| 31005 | ||||
| 31006 | if ( player.gui_mode == GUI_MODE_NONE ) | |||
| 31007 | { | |||
| 31008 | player.shootmode = true; | |||
| 31009 | } | |||
| 31010 | else | |||
| 31011 | { | |||
| 31012 | player.GUI.returnToPreviousActiveModule(); | |||
| 31013 | } | |||
| 31014 | } | |||
| 31015 | ||||
| 31016 | static ConsoleVariable<bool> cvar_skillsheet_blit("/skillsheet_blit", true); | |||
| 31017 | void Player::SkillSheet_t::openSkillSheet() | |||
| 31018 | { | |||
| 31019 | player.GUI.previousModule = player.GUI.activeModule; | |||
| 31020 | if ( player.shootmode ) | |||
| 31021 | { | |||
| 31022 | players[player.playernum]->openStatusScreen(GUI_MODE_NONE, | |||
| 31023 | INVENTORY_MODE_ITEM, player.GUI.MODULE_SKILLS_LIST); | |||
| 31024 | } | |||
| 31025 | else | |||
| 31026 | { | |||
| 31027 | players[player.playernum]->openStatusScreen(GUI_MODE_INVENTORY, | |||
| 31028 | players[player.playernum]->inventory_mode, player.GUI.MODULE_SKILLS_LIST); // Reset the GUI to the inventory. | |||
| 31029 | } | |||
| 31030 | if ( !bSkillSheetOpen ) | |||
| 31031 | { | |||
| 31032 | Player::soundActivate(); | |||
| 31033 | } | |||
| 31034 | bSkillSheetOpen = true; | |||
| 31035 | openTick = ticks; | |||
| 31036 | scrollPercent = 0.0; | |||
| 31037 | if ( skillFrame ) | |||
| 31038 | { | |||
| 31039 | auto innerFrame = skillFrame->findFrame("skills frame"); | |||
| 31040 | innerFrame->setBlitChildren(*cvar_skillsheet_blit); | |||
| 31041 | auto skillDescriptionFrame = innerFrame->findFrame("skill desc frame"); | |||
| 31042 | auto slider = skillDescriptionFrame->findSlider("skill slider"); | |||
| 31043 | slider->setValue(0.0); | |||
| 31044 | } | |||
| 31045 | resetSkillDisplay(); | |||
| 31046 | if ( selectedSkill < 0 ) | |||
| 31047 | { | |||
| 31048 | selectSkill(0); | |||
| 31049 | } | |||
| 31050 | if ( !::inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 31051 | { | |||
| 31052 | highlightedSkill = selectedSkill; | |||
| 31053 | } | |||
| 31054 | if ( bUseCompactSkillsView || bSlideWindowsOnly ) | |||
| 31055 | { | |||
| 31056 | if ( selectedSkill >= 8 ) | |||
| 31057 | { | |||
| 31058 | skillSlideAmount = 1.0; | |||
| 31059 | skillSlideDirection = 1; | |||
| 31060 | } | |||
| 31061 | else | |||
| 31062 | { | |||
| 31063 | skillSlideAmount = -1.0; | |||
| 31064 | skillSlideDirection = -1; | |||
| 31065 | } | |||
| 31066 | } | |||
| 31067 | } | |||
| 31068 | ||||
| 31069 | std::string formatSkillSheetEffects(int playernum, int proficiency, std::string& tag, std::string& rawValue) | |||
| 31070 | { | |||
| 31071 | char buf[1024] = ""; | |||
| 31072 | if ( !players[playernum] ) { return ""; } | |||
| 31073 | Entity* player = players[playernum]->entity; | |||
| 31074 | real_t val = 0.0; | |||
| 31075 | real_t val2 = 0.0; | |||
| 31076 | if ( proficiency == PRO_STEALTH ) | |||
| 31077 | { | |||
| 31078 | if ( tag == "STEALTH_VIS_REDUCTION" ) | |||
| 31079 | { | |||
| 31080 | //val = stats[playernum]->getModifiedProficiency(proficiency) * 2 * 100 / 512.f; // % visibility reduction | |||
| 31081 | val = 100.f * (255 - TOUCHRANGE32) * (1.0 * (stats[playernum]->getModifiedProficiency(PRO_STEALTH) / 100.f)) / 255.f; | |||
| 31082 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31083 | } | |||
| 31084 | else if ( tag == "STEALTH_SNEAK_VIS" ) | |||
| 31085 | { | |||
| 31086 | val = (2 + (stats[playernum]->getModifiedProficiency(proficiency) / 40)); // night vision when sneaking | |||
| 31087 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31088 | } | |||
| 31089 | else if ( tag == "STEALTH_BACKSTAB" ) | |||
| 31090 | { | |||
| 31091 | val = (stats[playernum]->getModifiedProficiency(proficiency) / 20 + 2) * 2; // backstab dmg | |||
| 31092 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31093 | { | |||
| 31094 | val *= 2; | |||
| 31095 | } | |||
| 31096 | if ( stats[playernum]->helmet && stats[playernum]->helmet->type == HAT_HOOD_ASSASSIN ) | |||
| 31097 | { | |||
| 31098 | if ( stats[playernum]->helmet->beatitude >= 0 || shouldInvertEquipmentBeatitude(stats[playernum]) ) | |||
| 31099 | { | |||
| 31100 | val += std::min(4 + (2 * abs(stats[playernum]->helmet->beatitude)), 8); | |||
| 31101 | } | |||
| 31102 | else | |||
| 31103 | { | |||
| 31104 | val /= 2; | |||
| 31105 | } | |||
| 31106 | } | |||
| 31107 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31108 | } | |||
| 31109 | else if ( tag == "STEALTH_CURRENT_VIS" ) | |||
| 31110 | { | |||
| 31111 | if ( player ) | |||
| 31112 | { | |||
| 31113 | val = player->entityLightAfterReductions(*stats[playernum], nullptr); | |||
| 31114 | val = std::max(1, (static_cast<int>(val / 16.0))); // general visibility | |||
| 31115 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31116 | } | |||
| 31117 | else | |||
| 31118 | { | |||
| 31119 | return "-"; | |||
| 31120 | } | |||
| 31121 | } | |||
| 31122 | return buf; | |||
| 31123 | } | |||
| 31124 | else if ( proficiency == PRO_RANGED ) | |||
| 31125 | { | |||
| 31126 | if ( tag == "RANGED_DMG_RANGE" ) | |||
| 31127 | { | |||
| 31128 | if ( proficiency == PRO_POLEARM ) | |||
| 31129 | { | |||
| 31130 | val = 100 - (100 - stats[playernum]->getModifiedProficiency(proficiency)) / 3.f; // lowest damage roll | |||
| 31131 | } | |||
| 31132 | else | |||
| 31133 | { | |||
| 31134 | val = 100 - (100 - stats[playernum]->getModifiedProficiency(proficiency)) / 2.f; // lowest damage roll | |||
| 31135 | } | |||
| 31136 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31137 | } | |||
| 31138 | else if ( tag == "RANGED_DMG_EFFECTIVENESS" ) | |||
| 31139 | { | |||
| 31140 | if ( proficiency == PRO_POLEARM ) | |||
| 31141 | { | |||
| 31142 | val = -25 + (stats[playernum]->getModifiedProficiency(proficiency) / 2); // -25% to +25% | |||
| 31143 | } | |||
| 31144 | else | |||
| 31145 | { | |||
| 31146 | val = -25 + (stats[playernum]->getModifiedProficiency(proficiency) / 2); // -25% to +25% | |||
| 31147 | } | |||
| 31148 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31149 | } | |||
| 31150 | else if ( tag == "RANGED_DEGRADE_CHANCE" ) | |||
| 31151 | { | |||
| 31152 | val = 50 + static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20) * 10; | |||
| 31153 | if ( stats[playernum]->type == GOBLIN ) | |||
| 31154 | { | |||
| 31155 | val += 20; | |||
| 31156 | if ( stats[playernum]->getModifiedProficiency(proficiency) < SKILL_LEVEL_LEGENDARY ) | |||
| 31157 | { | |||
| 31158 | val = std::min(val, 90.0); | |||
| 31159 | } | |||
| 31160 | } | |||
| 31161 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31162 | { | |||
| 31163 | val = 0.0; | |||
| 31164 | } | |||
| 31165 | if ( val > 0.0001 ) | |||
| 31166 | { | |||
| 31167 | val = 100 / val; | |||
| 31168 | } | |||
| 31169 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31170 | } | |||
| 31171 | else if ( tag == "RANGED_THROWN_DMG" ) | |||
| 31172 | { | |||
| 31173 | int skillLVL = stats[playernum]->getModifiedProficiency(proficiency) / 20; // thrown dmg bonus | |||
| 31174 | // +0% baseline | |||
| 31175 | val = 100 * (thrownDamageSkillMultipliers[std::min(skillLVL, 5)] - thrownDamageSkillMultipliers[0]); | |||
| 31176 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31177 | } | |||
| 31178 | else if ( tag == "RANGED_PIERCE_CHANCE" ) | |||
| 31179 | { | |||
| 31180 | val = std::min(std::max(statGetPER(stats[playernum], player) / 2, 0), 50); | |||
| 31181 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31182 | } | |||
| 31183 | return buf; | |||
| 31184 | } | |||
| 31185 | else if ( proficiency == PRO_SHIELD ) | |||
| 31186 | { | |||
| 31187 | if ( tag == "BLOCK_AC_INCREASE" ) | |||
| 31188 | { | |||
| 31189 | val = stats[playernum]->getActiveShieldBonus(false); | |||
| 31190 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31191 | } | |||
| 31192 | else if ( tag == "PASSIVE_AC_INCREASE" ) | |||
| 31193 | { | |||
| 31194 | val = stats[playernum]->getPassiveShieldBonus(false); | |||
| 31195 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31196 | } | |||
| 31197 | else if ( tag == "BLOCK_DEGRADE_NORMAL_CHANCE" ) | |||
| 31198 | { | |||
| 31199 | val = 25 + (stats[playernum]->type == GOBLIN ? 10 : 0); // degrade > 0 dmg taken | |||
| 31200 | val += 2 * (static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 10)); | |||
| 31201 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31202 | { | |||
| 31203 | val = 0.0; | |||
| 31204 | } | |||
| 31205 | if ( val > 0.0001 ) | |||
| 31206 | { | |||
| 31207 | val = 100 / val; | |||
| 31208 | } | |||
| 31209 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31210 | } | |||
| 31211 | else if ( tag == "BLOCK_DEGRADE_DEFENDING_CHANCE" ) | |||
| 31212 | { | |||
| 31213 | val = 10 + (stats[playernum]->type == GOBLIN ? 10 : 0); // degrade on 0 dmg | |||
| 31214 | if ( svFlags & SV_FLAG_HARDCORE ) | |||
| 31215 | { | |||
| 31216 | val = 40 + (stats[playernum]->type == GOBLIN ? 10 : 0); | |||
| 31217 | } | |||
| 31218 | val += 2 * (static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 10)); | |||
| 31219 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31220 | { | |||
| 31221 | val = 0.0; | |||
| 31222 | } | |||
| 31223 | if ( val > 0.0001 ) | |||
| 31224 | { | |||
| 31225 | val = 100 / val; | |||
| 31226 | } | |||
| 31227 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31228 | } | |||
| 31229 | return buf; | |||
| 31230 | } | |||
| 31231 | else if ( proficiency == PRO_UNARMED ) | |||
| 31232 | { | |||
| 31233 | if ( tag == "UNARMED_DMG_RANGE" ) | |||
| 31234 | { | |||
| 31235 | if ( proficiency == PRO_POLEARM ) | |||
| 31236 | { | |||
| 31237 | val = 100 - (100 - stats[playernum]->getModifiedProficiency(proficiency)) / 3.f; // lowest damage roll | |||
| 31238 | } | |||
| 31239 | else | |||
| 31240 | { | |||
| 31241 | val = 100 - (100 - stats[playernum]->getModifiedProficiency(proficiency)) / 2.f; // lowest damage roll | |||
| 31242 | } | |||
| 31243 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31244 | } | |||
| 31245 | else if ( tag == "UNARMED_DMG_EFFECTIVENESS" ) | |||
| 31246 | { | |||
| 31247 | if ( proficiency == PRO_POLEARM ) | |||
| 31248 | { | |||
| 31249 | val = -25 + (stats[playernum]->getModifiedProficiency(proficiency) / 2); // -25% to +25% | |||
| 31250 | } | |||
| 31251 | else | |||
| 31252 | { | |||
| 31253 | val = -25 + (stats[playernum]->getModifiedProficiency(proficiency) / 2); // -25% to +25% | |||
| 31254 | } | |||
| 31255 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31256 | } | |||
| 31257 | else if ( tag == "UNARMED_BONUS_DMG" ) | |||
| 31258 | { | |||
| 31259 | val = static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20); | |||
| 31260 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31261 | } | |||
| 31262 | else if ( tag == "GLOVE_DEGRADE_CHANCE" ) | |||
| 31263 | { | |||
| 31264 | val = 100 + (stats[playernum]->type == GOBLIN ? 20 : 0); // chance to degrade on > 0 dmg | |||
| 31265 | val += (static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20)) * 10; | |||
| 31266 | if ( svFlags & SV_FLAG_HARDCORE ) | |||
| 31267 | { | |||
| 31268 | val *= 2; | |||
| 31269 | } | |||
| 31270 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31271 | { | |||
| 31272 | val = 0.0; | |||
| 31273 | } | |||
| 31274 | if ( val > 0.0001 ) | |||
| 31275 | { | |||
| 31276 | val = 100 / val; | |||
| 31277 | } | |||
| 31278 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31279 | } | |||
| 31280 | else if ( tag == "GLOVE_DEGRADE0_CHANCE" ) | |||
| 31281 | { | |||
| 31282 | val = 8 + (stats[playernum]->type == GOBLIN ? 4 : 0); // chance to degrade on 0 dmg | |||
| 31283 | val += static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20); | |||
| 31284 | if ( svFlags & SV_FLAG_HARDCORE ) | |||
| 31285 | { | |||
| 31286 | val *= 2; | |||
| 31287 | } | |||
| 31288 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31289 | { | |||
| 31290 | val = 0.0; | |||
| 31291 | } | |||
| 31292 | if ( val > 0.0001 ) | |||
| 31293 | { | |||
| 31294 | val = 100 / val; | |||
| 31295 | } | |||
| 31296 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31297 | } | |||
| 31298 | else if ( tag == "UNARMED_KNOCKBACK_DIST" ) | |||
| 31299 | { | |||
| 31300 | val = static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20) * 20; | |||
| 31301 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31302 | } | |||
| 31303 | return buf; | |||
| 31304 | } | |||
| 31305 | else if ( proficiency == PRO_SWORD ) | |||
| 31306 | { | |||
| 31307 | if ( tag == "SWORD_DMG_RANGE" ) | |||
| 31308 | { | |||
| 31309 | if ( proficiency == PRO_POLEARM ) | |||
| 31310 | { | |||
| 31311 | val = 100 - (100 - stats[playernum]->getModifiedProficiency(proficiency)) / 3.f; // lowest damage roll | |||
| 31312 | } | |||
| 31313 | else | |||
| 31314 | { | |||
| 31315 | val = 100 - (100 - stats[playernum]->getModifiedProficiency(proficiency)) / 2.f; // lowest damage roll | |||
| 31316 | } | |||
| 31317 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31318 | } | |||
| 31319 | else if ( tag == "SWORD_DMG_EFFECTIVENESS" ) | |||
| 31320 | { | |||
| 31321 | if ( proficiency == PRO_POLEARM ) | |||
| 31322 | { | |||
| 31323 | val = -25 + (stats[playernum]->getModifiedProficiency(proficiency) / 2); // -25% to +25% | |||
| 31324 | } | |||
| 31325 | else | |||
| 31326 | { | |||
| 31327 | val = -25 + (stats[playernum]->getModifiedProficiency(proficiency) / 2); // -25% to +25% | |||
| 31328 | } | |||
| 31329 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31330 | } | |||
| 31331 | else if ( tag == "SWORD_DEGRADE_CHANCE" ) | |||
| 31332 | { | |||
| 31333 | val = 50 + (stats[playernum]->type == GOBLIN ? 20 : 0); // chance to degrade on > 0 dmg | |||
| 31334 | val += (static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20)) * 10; | |||
| 31335 | if ( svFlags & SV_FLAG_HARDCORE ) | |||
| 31336 | { | |||
| 31337 | val *= 2; | |||
| 31338 | } | |||
| 31339 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31340 | { | |||
| 31341 | val = 0.0; | |||
| 31342 | } | |||
| 31343 | if ( val > 0.0001 ) | |||
| 31344 | { | |||
| 31345 | val = 100 / val; | |||
| 31346 | } | |||
| 31347 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31348 | } | |||
| 31349 | else if ( tag == "SWORD_DEGRADE0_CHANCE" ) | |||
| 31350 | { | |||
| 31351 | val = 4 + (stats[playernum]->type == GOBLIN ? 4 : 0); // chance to degrade on 0 dmg | |||
| 31352 | val += static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20); | |||
| 31353 | if ( svFlags & SV_FLAG_HARDCORE ) | |||
| 31354 | { | |||
| 31355 | val *= 2; | |||
| 31356 | } | |||
| 31357 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31358 | { | |||
| 31359 | val = 0.0; | |||
| 31360 | } | |||
| 31361 | if ( val > 0.0001 ) | |||
| 31362 | { | |||
| 31363 | val = 100 / val; | |||
| 31364 | } | |||
| 31365 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31366 | } | |||
| 31367 | return buf; | |||
| 31368 | } | |||
| 31369 | else if ( proficiency == PRO_POLEARM ) | |||
| 31370 | { | |||
| 31371 | if ( tag == "POLEARM_DMG_RANGE" ) | |||
| 31372 | { | |||
| 31373 | if ( proficiency == PRO_POLEARM ) | |||
| 31374 | { | |||
| 31375 | val = 100 - (100 - stats[playernum]->getModifiedProficiency(proficiency)) / 3.f; // lowest damage roll | |||
| 31376 | } | |||
| 31377 | else | |||
| 31378 | { | |||
| 31379 | val = 100 - (100 - stats[playernum]->getModifiedProficiency(proficiency)) / 2.f; // lowest damage roll | |||
| 31380 | } | |||
| 31381 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31382 | } | |||
| 31383 | else if ( tag == "POLEARM_DMG_EFFECTIVENESS" ) | |||
| 31384 | { | |||
| 31385 | if ( proficiency == PRO_POLEARM ) | |||
| 31386 | { | |||
| 31387 | val = -25 + (stats[playernum]->getModifiedProficiency(proficiency) / 2); // -25% to +25% | |||
| 31388 | } | |||
| 31389 | else | |||
| 31390 | { | |||
| 31391 | val = -25 + (stats[playernum]->getModifiedProficiency(proficiency) / 2); // -25% to +25% | |||
| 31392 | } | |||
| 31393 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31394 | } | |||
| 31395 | else if ( tag == "POLEARM_DEGRADE_CHANCE" ) | |||
| 31396 | { | |||
| 31397 | val = 50 + (stats[playernum]->type == GOBLIN ? 20 : 0); // chance to degrade on > 0 dmg | |||
| 31398 | val += (static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20)) * 10; | |||
| 31399 | if ( svFlags & SV_FLAG_HARDCORE ) | |||
| 31400 | { | |||
| 31401 | val *= 2; | |||
| 31402 | } | |||
| 31403 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31404 | { | |||
| 31405 | val = 0.0; | |||
| 31406 | } | |||
| 31407 | if ( val > 0.0001 ) | |||
| 31408 | { | |||
| 31409 | val = 100 / val; | |||
| 31410 | } | |||
| 31411 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31412 | } | |||
| 31413 | else if ( tag == "POLEARM_DEGRADE0_CHANCE" ) | |||
| 31414 | { | |||
| 31415 | val = 4 + (stats[playernum]->type == GOBLIN ? 4 : 0); // chance to degrade on 0 dmg | |||
| 31416 | val += static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20); | |||
| 31417 | if ( svFlags & SV_FLAG_HARDCORE ) | |||
| 31418 | { | |||
| 31419 | val *= 2; | |||
| 31420 | } | |||
| 31421 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31422 | { | |||
| 31423 | val = 0.0; | |||
| 31424 | } | |||
| 31425 | if ( val > 0.0001 ) | |||
| 31426 | { | |||
| 31427 | val = 100 / val; | |||
| 31428 | } | |||
| 31429 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31430 | } | |||
| 31431 | return buf; | |||
| 31432 | } | |||
| 31433 | else if ( proficiency == PRO_AXE ) | |||
| 31434 | { | |||
| 31435 | if ( tag == "AXE_DMG_RANGE" ) | |||
| 31436 | { | |||
| 31437 | if ( proficiency == PRO_POLEARM ) | |||
| 31438 | { | |||
| 31439 | val = 100 - (100 - stats[playernum]->getModifiedProficiency(proficiency)) / 3.f; // lowest damage roll | |||
| 31440 | } | |||
| 31441 | else | |||
| 31442 | { | |||
| 31443 | val = 100 - (100 - stats[playernum]->getModifiedProficiency(proficiency)) / 2.f; // lowest damage roll | |||
| 31444 | } | |||
| 31445 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31446 | } | |||
| 31447 | else if ( tag == "AXE_DMG_EFFECTIVENESS" ) | |||
| 31448 | { | |||
| 31449 | if ( proficiency == PRO_POLEARM ) | |||
| 31450 | { | |||
| 31451 | val = -25 + (stats[playernum]->getModifiedProficiency(proficiency) / 2); // -25% to +25% | |||
| 31452 | } | |||
| 31453 | else | |||
| 31454 | { | |||
| 31455 | val = -25 + (stats[playernum]->getModifiedProficiency(proficiency) / 2); // -25% to +25% | |||
| 31456 | } | |||
| 31457 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31458 | } | |||
| 31459 | else if ( tag == "AXE_DEGRADE_CHANCE" ) | |||
| 31460 | { | |||
| 31461 | val = 50 + (stats[playernum]->type == GOBLIN ? 20 : 0); // chance to degrade on > 0 dmg | |||
| 31462 | val += (static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20)) * 10; | |||
| 31463 | if ( svFlags & SV_FLAG_HARDCORE ) | |||
| 31464 | { | |||
| 31465 | val *= 2; | |||
| 31466 | } | |||
| 31467 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31468 | { | |||
| 31469 | val = 0.0; | |||
| 31470 | } | |||
| 31471 | if ( val > 0.0001 ) | |||
| 31472 | { | |||
| 31473 | val = 100 / val; | |||
| 31474 | } | |||
| 31475 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31476 | } | |||
| 31477 | else if ( tag == "AXE_DEGRADE0_CHANCE" ) | |||
| 31478 | { | |||
| 31479 | val = 4 + (stats[playernum]->type == GOBLIN ? 4 : 0); // chance to degrade on 0 dmg | |||
| 31480 | val += static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20); | |||
| 31481 | if ( svFlags & SV_FLAG_HARDCORE ) | |||
| 31482 | { | |||
| 31483 | val *= 2; | |||
| 31484 | } | |||
| 31485 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31486 | { | |||
| 31487 | val = 0.0; | |||
| 31488 | } | |||
| 31489 | if ( val > 0.0001 ) | |||
| 31490 | { | |||
| 31491 | val = 100 / val; | |||
| 31492 | } | |||
| 31493 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31494 | } | |||
| 31495 | return buf; | |||
| 31496 | } | |||
| 31497 | else if ( proficiency == PRO_MACE ) | |||
| 31498 | { | |||
| 31499 | if ( tag == "MACE_DMG_RANGE" ) | |||
| 31500 | { | |||
| 31501 | if ( proficiency == PRO_POLEARM ) | |||
| 31502 | { | |||
| 31503 | val = 100 - (100 - stats[playernum]->getModifiedProficiency(proficiency)) / 3.f; // lowest damage roll | |||
| 31504 | } | |||
| 31505 | else | |||
| 31506 | { | |||
| 31507 | val = 100 - (100 - stats[playernum]->getModifiedProficiency(proficiency)) / 2.f; // lowest damage roll | |||
| 31508 | } | |||
| 31509 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31510 | } | |||
| 31511 | else if ( tag == "MACE_DMG_EFFECTIVENESS" ) | |||
| 31512 | { | |||
| 31513 | if ( proficiency == PRO_POLEARM ) | |||
| 31514 | { | |||
| 31515 | val = -25 + (stats[playernum]->getModifiedProficiency(proficiency) / 2); // -25% to +25% | |||
| 31516 | } | |||
| 31517 | else | |||
| 31518 | { | |||
| 31519 | val = -25 + (stats[playernum]->getModifiedProficiency(proficiency) / 2); // -25% to +25% | |||
| 31520 | } | |||
| 31521 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31522 | } | |||
| 31523 | else if ( tag == "MACE_DEGRADE_CHANCE" ) | |||
| 31524 | { | |||
| 31525 | val = 50 + (stats[playernum]->type == GOBLIN ? 20 : 0); // chance to degrade on > 0 dmg | |||
| 31526 | val += (static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20)) * 10; | |||
| 31527 | if ( svFlags & SV_FLAG_HARDCORE ) | |||
| 31528 | { | |||
| 31529 | val *= 2; | |||
| 31530 | } | |||
| 31531 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31532 | { | |||
| 31533 | val = 0.0; | |||
| 31534 | } | |||
| 31535 | if ( val > 0.0001 ) | |||
| 31536 | { | |||
| 31537 | val = 100 / val; | |||
| 31538 | } | |||
| 31539 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31540 | } | |||
| 31541 | else if ( tag == "MACE_DEGRADE0_CHANCE" ) | |||
| 31542 | { | |||
| 31543 | val = 4 + (stats[playernum]->type == GOBLIN ? 4 : 0); // chance to degrade on 0 dmg | |||
| 31544 | val += static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20); | |||
| 31545 | if ( svFlags & SV_FLAG_HARDCORE ) | |||
| 31546 | { | |||
| 31547 | val *= 2; | |||
| 31548 | } | |||
| 31549 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31550 | { | |||
| 31551 | val = 0.0; | |||
| 31552 | } | |||
| 31553 | if ( val > 0.0001 ) | |||
| 31554 | { | |||
| 31555 | val = 100 / val; | |||
| 31556 | } | |||
| 31557 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31558 | } | |||
| 31559 | return buf; | |||
| 31560 | } | |||
| 31561 | else if ( proficiency == PRO_SWIMMING ) | |||
| 31562 | { | |||
| 31563 | if ( tag == "SWIM_SPEED_TOTAL" ) | |||
| 31564 | { | |||
| 31565 | val = (((stats[playernum]->getModifiedProficiency(proficiency) / 100.f) * 50.f) + 50); // water movement speed | |||
| 31566 | if ( stats[playernum]->type == SKELETON ) | |||
| 31567 | { | |||
| 31568 | val *= .5; | |||
| 31569 | } | |||
| 31570 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31571 | } | |||
| 31572 | else if ( tag == "SWIM_SPEED_BASE" ) | |||
| 31573 | { | |||
| 31574 | val = -50.0; // water movement speed | |||
| 31575 | if ( stats[playernum]->type == SKELETON ) | |||
| 31576 | { | |||
| 31577 | val -= 25.0; | |||
| 31578 | } | |||
| 31579 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31580 | } | |||
| 31581 | else if ( tag == "SWIM_SPEED_BONUS" ) | |||
| 31582 | { | |||
| 31583 | val = (((stats[playernum]->getModifiedProficiency(proficiency) / 100.f) * 50.f)); // water movement speed | |||
| 31584 | if ( stats[playernum]->type == SKELETON ) | |||
| 31585 | { | |||
| 31586 | val *= .5; | |||
| 31587 | } | |||
| 31588 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31589 | } | |||
| 31590 | return buf; | |||
| 31591 | } | |||
| 31592 | else if ( proficiency == PRO_LEADERSHIP ) | |||
| 31593 | { | |||
| 31594 | if ( tag == "LEADER_MAX_FOLLOWERS" ) | |||
| 31595 | { | |||
| 31596 | val = std::min(8, std::max(4, 2 * (stats[playernum]->getModifiedProficiency(proficiency) / 20))); // max followers | |||
| 31597 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31598 | } | |||
| 31599 | else if ( tag == "LEADER_FOLLOWER_SPEED" ) | |||
| 31600 | { | |||
| 31601 | val = 1 + (stats[playernum]->getModifiedProficiency(proficiency) / 20); | |||
| 31602 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31603 | } | |||
| 31604 | else if ( tag == "LEADER_CHARM_MONSTER" ) | |||
| 31605 | { | |||
| 31606 | val = 80 + ((statGetCHR(stats[playernum], player) + stats[playernum]->getModifiedProficiency(proficiency)) / 20) * 10; | |||
| 31607 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31608 | } | |||
| 31609 | else if ( tag == "LIST_LEADER_AVAILABLE_FOLLOWERS" ) | |||
| 31610 | { | |||
| 31611 | std::string outputList = ""; | |||
| 31612 | Monster playerRace = stats[playernum]->type; | |||
| 31613 | std::map<Monster, std::vector<Monster>>* allyTable = &Player::SkillSheet_t::skillSheetData.leadershipAllyTableBase; | |||
| 31614 | enum TableOrder : int | |||
| 31615 | { | |||
| 31616 | LEADER_BASE_TABLE, | |||
| 31617 | LEADER_UNIQUE_TABLE, | |||
| 31618 | LEADER_CAPSTONE_TABLE, | |||
| 31619 | TABLE_MAX | |||
| 31620 | }; | |||
| 31621 | for ( int i = LEADER_BASE_TABLE; i < TABLE_MAX; ++i ) | |||
| 31622 | { | |||
| 31623 | if ( i == LEADER_CAPSTONE_TABLE ) | |||
| 31624 | { | |||
| 31625 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31626 | { | |||
| 31627 | allyTable = &Player::SkillSheet_t::skillSheetData.leadershipAllyTableLegendary; | |||
| 31628 | } | |||
| 31629 | else | |||
| 31630 | { | |||
| 31631 | continue; | |||
| 31632 | } | |||
| 31633 | } | |||
| 31634 | if ( i == LEADER_CAPSTONE_TABLE || i == LEADER_BASE_TABLE ) | |||
| 31635 | { | |||
| 31636 | if ( allyTable->find(playerRace) != allyTable->end() ) | |||
| 31637 | { | |||
| 31638 | if ( !(*allyTable)[playerRace].empty() ) | |||
| 31639 | { | |||
| 31640 | for ( auto& ally : (*allyTable)[playerRace] ) | |||
| 31641 | { | |||
| 31642 | if ( ally < 0 || ally >= NUMMONSTERS ) { continue; } | |||
| 31643 | std::string monsterName = ""; | |||
| 31644 | monsterName = getMonsterLocalizedName(ally); | |||
| 31645 | capitalizeString(monsterName); | |||
| 31646 | if ( outputList != "" ) | |||
| 31647 | { | |||
| 31648 | outputList += '\n'; | |||
| 31649 | } | |||
| 31650 | outputList += "\x1E " + monsterName; | |||
| 31651 | } | |||
| 31652 | } | |||
| 31653 | } | |||
| 31654 | } | |||
| 31655 | else if ( i == LEADER_UNIQUE_TABLE ) | |||
| 31656 | { | |||
| 31657 | auto* allyTable = &Player::SkillSheet_t::skillSheetData.leadershipAllyTableSpecialRecruitment; | |||
| 31658 | if ( allyTable->find(playerRace) != allyTable->end() ) | |||
| 31659 | { | |||
| 31660 | if ( !(*allyTable)[playerRace].empty() ) | |||
| 31661 | { | |||
| 31662 | for ( auto& allyPair : (*allyTable)[playerRace] ) | |||
| 31663 | { | |||
| 31664 | auto& ally = allyPair.first; | |||
| 31665 | if ( ally < 0 || ally >= NUMMONSTERS ) { continue; } | |||
| 31666 | std::string monsterName = ""; | |||
| 31667 | monsterName = getMonsterLocalizedName(ally); | |||
| 31668 | capitalizeString(monsterName); | |||
| 31669 | if ( outputList != "" ) | |||
| 31670 | { | |||
| 31671 | outputList += '\n'; | |||
| 31672 | } | |||
| 31673 | outputList += "\x1E " + monsterName; | |||
| 31674 | outputList += "\n" + allyPair.second; | |||
| 31675 | } | |||
| 31676 | } | |||
| 31677 | } | |||
| 31678 | } | |||
| 31679 | } | |||
| 31680 | if ( outputList == "" ) { outputList = "-"; } | |||
| 31681 | snprintf(buf, sizeof(buf), rawValue.c_str(), outputList.c_str()); | |||
| 31682 | } | |||
| 31683 | return buf; | |||
| 31684 | } | |||
| 31685 | else if ( proficiency == PRO_TRADING ) | |||
| 31686 | { | |||
| 31687 | if ( tag == "TRADING_BUY_PRICE" ) | |||
| 31688 | { | |||
| 31689 | val = 1 / ((50 + stats[playernum]->getModifiedProficiency(proficiency)) / 150.f); // buy value | |||
| 31690 | //val /= 1.f + statGetCHR(stats[playernum], players[playernum]->entity) / 20.f; | |||
| 31691 | val = std::max(1.0, val); | |||
| 31692 | val = val * 100.0 - 100.0; | |||
| 31693 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31694 | } | |||
| 31695 | else if ( tag == "TRADING_SELL_PRICE" ) | |||
| 31696 | { | |||
| 31697 | val = (50 + stats[playernum]->getModifiedProficiency(proficiency)) / 150.f; // sell value | |||
| 31698 | val *= 1.f + statGetCHR(stats[playernum], players[playernum]->entity) / 20.f; | |||
| 31699 | val = std::min(1.0, val); | |||
| 31700 | val = val * 100.0 - 100.0; | |||
| 31701 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31702 | } | |||
| 31703 | return buf; | |||
| 31704 | } | |||
| 31705 | else if ( proficiency == PRO_APPRAISAL ) | |||
| 31706 | { | |||
| 31707 | if ( tag == "APPRAISE_GOLD_SPEED" ) | |||
| 31708 | { | |||
| 31709 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31710 | { | |||
| 31711 | snprintf(buf, sizeof(buf), "%s", Language::get(4064)); // "instant" | |||
| 31712 | } | |||
| 31713 | else | |||
| 31714 | { | |||
| 31715 | val = (60.f / (stats[playernum]->getModifiedProficiency(proficiency) + 1)) / (TICKS_PER_SECOND50); // appraisal time per gold value | |||
| 31716 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31717 | } | |||
| 31718 | } | |||
| 31719 | else if ( tag == "APPRAISE_MAX_GOLD_VALUE" ) | |||
| 31720 | { | |||
| 31721 | if ( skillCapstoneUnlocked(playernum, proficiency) ) | |||
| 31722 | { | |||
| 31723 | snprintf(buf, sizeof(buf), "%s", Language::get(4065)); // "any" | |||
| 31724 | } | |||
| 31725 | else | |||
| 31726 | { | |||
| 31727 | val = 10 * (stats[playernum]->getModifiedProficiency(proficiency) + (statGetPER(stats[playernum], player) * 5)); // max gold value can appraise | |||
| 31728 | if ( val < 0.0 ) | |||
| 31729 | { | |||
| 31730 | snprintf(buf, sizeof(buf), "??? Gold"); | |||
| 31731 | } | |||
| 31732 | else if ( val < 0.1 ) | |||
| 31733 | { | |||
| 31734 | val = 9; | |||
| 31735 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31736 | } | |||
| 31737 | else | |||
| 31738 | { | |||
| 31739 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31740 | } | |||
| 31741 | } | |||
| 31742 | } | |||
| 31743 | else if ( tag == "APPRAISE_WORTHLESS_GLASS" ) | |||
| 31744 | { | |||
| 31745 | if ( (stats[playernum]->getModifiedProficiency(proficiency) + (statGetPER(stats[playernum], player) * 5)) >= 100 ) | |||
| 31746 | { | |||
| 31747 | snprintf(buf, sizeof(buf), rawValue.c_str(), Language::get(1314)); // yes | |||
| 31748 | } | |||
| 31749 | else | |||
| 31750 | { | |||
| 31751 | snprintf(buf, sizeof(buf), rawValue.c_str(), Language::get(1315)); // no | |||
| 31752 | } | |||
| 31753 | } | |||
| 31754 | return buf; | |||
| 31755 | } | |||
| 31756 | else if ( proficiency == PRO_LOCKPICKING ) | |||
| 31757 | { | |||
| 31758 | Sint32 PER = statGetPER(stats[playernum], player); | |||
| 31759 | if ( tag == "TINKERING_LOCKPICK_CHESTS_DOORS" ) | |||
| 31760 | { | |||
| 31761 | val = stats[playernum]->getModifiedProficiency(proficiency) / 2.f; // lockpick chests/doors | |||
| 31762 | if ( stats[playernum]->getModifiedProficiency(proficiency) >= SKILL_LEVEL_LEGENDARY ) | |||
| 31763 | { | |||
| 31764 | val = 100.f; | |||
| 31765 | } | |||
| 31766 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31767 | } | |||
| 31768 | else if ( tag == "TINKERING_SCRAP_CHESTS" ) | |||
| 31769 | { | |||
| 31770 | val = std::min(100.f, stats[playernum]->getModifiedProficiency(proficiency) + 50.f); | |||
| 31771 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31772 | } | |||
| 31773 | else if ( tag == "TINKERING_SCRAP_AUTOMATONS" ) | |||
| 31774 | { | |||
| 31775 | if ( stats[playernum]->getModifiedProficiency(proficiency) >= SKILL_LEVEL_EXPERT ) | |||
| 31776 | { | |||
| 31777 | val = 100.f; // lockpick automatons | |||
| 31778 | } | |||
| 31779 | else | |||
| 31780 | { | |||
| 31781 | val = (100 - 100 / (static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20 + 1))); // lockpick automatons | |||
| 31782 | } | |||
| 31783 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31784 | } | |||
| 31785 | else if ( tag == "TINKERING_DISARM_ARROWS" ) | |||
| 31786 | { | |||
| 31787 | val = (100 - 100 / (std::max(1, static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 10)))); // disarm arrow traps | |||
| 31788 | if ( stats[playernum]->getModifiedProficiency(proficiency) < SKILL_LEVEL_BASIC ) | |||
| 31789 | { | |||
| 31790 | val = 0.f; | |||
| 31791 | } | |||
| 31792 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31793 | } | |||
| 31794 | else if ( tag == "TINKERING_KIT_SCRAP_BONUS" ) | |||
| 31795 | { | |||
| 31796 | // bonus scrapping chances. | |||
| 31797 | int skillLVL = std::min(5, static_cast<int>((stats[playernum]->getModifiedProficiency(proficiency) + PER) / 20)); | |||
| 31798 | skillLVL = std::max(0, skillLVL); | |||
| 31799 | switch ( skillLVL ) | |||
| 31800 | { | |||
| 31801 | case 5: | |||
| 31802 | val = 150.f; | |||
| 31803 | break; | |||
| 31804 | case 4: | |||
| 31805 | val = 125.f; | |||
| 31806 | break; | |||
| 31807 | case 3: | |||
| 31808 | val = 50.f; | |||
| 31809 | break; | |||
| 31810 | case 2: | |||
| 31811 | val = 25.f; | |||
| 31812 | break; | |||
| 31813 | case 1: | |||
| 31814 | val = 12.5; | |||
| 31815 | break; | |||
| 31816 | default: | |||
| 31817 | val = 0.f; | |||
| 31818 | break; | |||
| 31819 | } | |||
| 31820 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31821 | } | |||
| 31822 | else if ( tag == "TINKERING_KIT_REPAIR_ITEM" ) | |||
| 31823 | { | |||
| 31824 | std::string canRepairItems = Language::get(4057); // none | |||
| 31825 | char metalbuf[64] = ""; | |||
| 31826 | char magicbuf[64] = ""; | |||
| 31827 | if ( (stats[playernum]->getModifiedProficiency(proficiency) + PER + (stats[playernum]->type == AUTOMATON ? 20 : 0)) >= SKILL_LEVEL_LEGENDARY ) | |||
| 31828 | { | |||
| 31829 | canRepairItems = Language::get(4058); // all | |||
| 31830 | } | |||
| 31831 | else if ( (stats[playernum]->getModifiedProficiency(proficiency) + PER + (stats[playernum]->type == AUTOMATON ? 20 : 0)) >= SKILL_LEVEL_MASTER ) | |||
| 31832 | { | |||
| 31833 | // 2/0 | |||
| 31834 | snprintf(metalbuf, sizeof(metalbuf), Language::get(4059), 2); | |||
| 31835 | snprintf(magicbuf, sizeof(magicbuf), Language::get(4060), 0); | |||
| 31836 | canRepairItems = "\x1E "; | |||
| 31837 | canRepairItems += metalbuf; | |||
| 31838 | canRepairItems += '\n'; | |||
| 31839 | canRepairItems += "\x1E "; | |||
| 31840 | canRepairItems += magicbuf; | |||
| 31841 | } | |||
| 31842 | else if ( (stats[playernum]->getModifiedProficiency(proficiency) + PER + (stats[playernum]->type == AUTOMATON ? 20 : 0)) >= SKILL_LEVEL_EXPERT ) | |||
| 31843 | { | |||
| 31844 | // 1/0 | |||
| 31845 | snprintf(metalbuf, sizeof(metalbuf), Language::get(4059), 1); | |||
| 31846 | snprintf(magicbuf, sizeof(magicbuf), Language::get(4060), 0); | |||
| 31847 | canRepairItems = "\x1E "; | |||
| 31848 | canRepairItems += metalbuf; | |||
| 31849 | canRepairItems += '\n'; | |||
| 31850 | canRepairItems += "\x1E "; | |||
| 31851 | canRepairItems += magicbuf; | |||
| 31852 | } | |||
| 31853 | snprintf(buf, sizeof(buf), rawValue.c_str(), canRepairItems.c_str()); | |||
| 31854 | } | |||
| 31855 | else if ( tag == "TINKERING_MAX_ALLIES" ) | |||
| 31856 | { | |||
| 31857 | val = maximumTinkeringBotsCanBeDeployed(stats[playernum]); | |||
| 31858 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31859 | } | |||
| 31860 | return buf; | |||
| 31861 | } | |||
| 31862 | else if ( proficiency == PRO_ALCHEMY ) | |||
| 31863 | { | |||
| 31864 | if ( tag == "ALCHEMY_POTION_EFFECT_DMG" ) | |||
| 31865 | { | |||
| 31866 | int skillLVL = stats[playernum]->getModifiedProficiency(proficiency) / 20; | |||
| 31867 | // +0% baseline | |||
| 31868 | val = 100 * (potionDamageSkillMultipliers[std::min(skillLVL, 5)] - potionDamageSkillMultipliers[0]); | |||
| 31869 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31870 | } | |||
| 31871 | else if ( tag == "ALCHEMY_THROWN_IMPACT_DMG" ) | |||
| 31872 | { | |||
| 31873 | int skillLVL = stats[playernum]->getModifiedProficiency(proficiency) / 20; | |||
| 31874 | // +0% baseline | |||
| 31875 | val = 100 * (potionDamageSkillMultipliers[std::min(skillLVL, 5)] - potionDamageSkillMultipliers[0]); | |||
| 31876 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31877 | } | |||
| 31878 | else if ( tag == "ALCHEMY_DUPLICATION_CHANCE" ) | |||
| 31879 | { | |||
| 31880 | val = 50.f + static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20) * 10; | |||
| 31881 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31882 | } | |||
| 31883 | else if ( tag == "ALCHEMY_EMPTY_BOTTLE_CONSUME" ) | |||
| 31884 | { | |||
| 31885 | val = std::min(80, (60 + static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20) * 10)); | |||
| 31886 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31887 | } | |||
| 31888 | else if ( tag == "ALCHEMY_EMPTY_BOTTLE_BREW" ) | |||
| 31889 | { | |||
| 31890 | val = 50.f + static_cast<int>(stats[playernum]->getModifiedProficiency(proficiency) / 20) * 5; | |||
| 31891 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31892 | } | |||
| 31893 | else if ( tag == "ALCHEMY_LEARNT_INGREDIENTS_BASE" ) | |||
| 31894 | { | |||
| 31895 | std::string outputList = ""; | |||
| 31896 | for ( auto it = clientLearnedAlchemyIngredients[playernum].begin(); | |||
| 31897 | it != clientLearnedAlchemyIngredients[playernum].end(); ++it ) | |||
| 31898 | { | |||
| 31899 | auto alchemyEntry = *it; | |||
| 31900 | if ( GenericGUI[playernum].isItemBaseIngredient(alchemyEntry) ) | |||
| 31901 | { | |||
| 31902 | std::string itemName = items[alchemyEntry].getIdentifiedName(); | |||
| 31903 | size_t pos = std::string::npos; | |||
| 31904 | for ( auto& potionName : Player::SkillSheet_t::skillSheetData.potionNamesToFilter ) | |||
| 31905 | { | |||
| 31906 | if ( (pos = itemName.find(potionName)) != std::string::npos ) | |||
| 31907 | { | |||
| 31908 | itemName.erase(pos, potionName.length()); | |||
| 31909 | } | |||
| 31910 | } | |||
| 31911 | capitalizeString(itemName); | |||
| 31912 | if ( outputList != "" ) | |||
| 31913 | { | |||
| 31914 | outputList += '\n'; | |||
| 31915 | } | |||
| 31916 | outputList += "\x1E " + itemName; | |||
| 31917 | } | |||
| 31918 | } | |||
| 31919 | if ( outputList == "" ) { outputList = "-"; } | |||
| 31920 | snprintf(buf, sizeof(buf), rawValue.c_str(), outputList.c_str()); | |||
| 31921 | } | |||
| 31922 | else if ( tag == "ALCHEMY_LEARNT_INGREDIENTS_SECONDARY" ) | |||
| 31923 | { | |||
| 31924 | std::string outputList = ""; | |||
| 31925 | for ( auto it = clientLearnedAlchemyIngredients[playernum].begin(); | |||
| 31926 | it != clientLearnedAlchemyIngredients[playernum].end(); ++it ) | |||
| 31927 | { | |||
| 31928 | auto alchemyEntry = *it; | |||
| 31929 | if ( GenericGUI[playernum].isItemSecondaryIngredient(alchemyEntry) | |||
| 31930 | && !GenericGUI[playernum].isItemBaseIngredient(alchemyEntry) ) | |||
| 31931 | { | |||
| 31932 | std::string itemName = items[alchemyEntry].getIdentifiedName(); | |||
| 31933 | size_t pos = std::string::npos; | |||
| 31934 | for ( auto& potionName : Player::SkillSheet_t::skillSheetData.potionNamesToFilter ) | |||
| 31935 | { | |||
| 31936 | if ( (pos = itemName.find(potionName)) != std::string::npos ) | |||
| 31937 | { | |||
| 31938 | itemName.erase(pos, potionName.length()); | |||
| 31939 | } | |||
| 31940 | } | |||
| 31941 | capitalizeString(itemName); | |||
| 31942 | if ( outputList != "" ) | |||
| 31943 | { | |||
| 31944 | outputList += '\n'; | |||
| 31945 | } | |||
| 31946 | outputList += "\x1E " + itemName; | |||
| 31947 | } | |||
| 31948 | } | |||
| 31949 | if ( outputList == "" ) { outputList = "-"; } | |||
| 31950 | snprintf(buf, sizeof(buf), rawValue.c_str(), outputList.c_str()); | |||
| 31951 | } | |||
| 31952 | return buf; | |||
| 31953 | } | |||
| 31954 | else if ( proficiency == PRO_SPELLCASTING ) | |||
| 31955 | { | |||
| 31956 | if ( tag == "CASTING_MP_REGEN" ) | |||
| 31957 | { | |||
| 31958 | if ( (stats[playernum])->playerRace == RACE_INSECTOID && (stats[playernum])->appearance == 0 ) | |||
| 31959 | { | |||
| 31960 | return Language::get(4066); | |||
| 31961 | } | |||
| 31962 | else if ( (stats[playernum])->type == AUTOMATON ) | |||
| 31963 | { | |||
| 31964 | return Language::get(4067); | |||
| 31965 | } | |||
| 31966 | else | |||
| 31967 | { | |||
| 31968 | val = getBaseManaRegen(player, *(stats[playernum])) / (TICKS_PER_SECOND50 * 1.f); | |||
| 31969 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 31970 | } | |||
| 31971 | } | |||
| 31972 | else if ( tag == "CASTING_MP_REGEN_SKILL_MULTIPLIER" ) | |||
| 31973 | { | |||
| 31974 | if ( (stats[playernum])->playerRace == RACE_INSECTOID && (stats[playernum])->appearance == 0 ) | |||
| 31975 | { | |||
| 31976 | return Language::get(4066); | |||
| 31977 | } | |||
| 31978 | else if ( (stats[playernum])->type == AUTOMATON ) | |||
| 31979 | { | |||
| 31980 | return Language::get(4067); | |||
| 31981 | } | |||
| 31982 | else | |||
| 31983 | { | |||
| 31984 | val = 0.0; | |||
| 31985 | int skill = stats[playernum]->getModifiedProficiency(proficiency); | |||
| 31986 | int multiplier = (skill / 20) + 1; | |||
| 31987 | val = multiplier; | |||
| 31988 | //real_t normalValue = player->getBaseManaRegen(*(stats[playernum])) / (TICKS_PER_SECOND * 1.f); | |||
| 31989 | //stats[playernum]->getModifiedProficiency(proficiency) = 0; | |||
| 31990 | //real_t zeroValue = player->getBaseManaRegen(*(stats[playernum])) / (TICKS_PER_SECOND * 1.f); | |||
| 31991 | //stats[playernum]->getModifiedProficiency(proficiency) = skill; | |||
| 31992 | // | |||
| 31993 | //val = (100 * zeroValue / normalValue) - 100; | |||
| 31994 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 31995 | } | |||
| 31996 | } | |||
| 31997 | else if ( tag == "CASTING_MP_REGEN_SKILL_BONUS" ) | |||
| 31998 | { | |||
| 31999 | val = 0.0; | |||
| 32000 | int skill = stats[playernum]->getProficiency(proficiency); | |||
| 32001 | real_t normalValue = getBaseManaRegen(player, *(stats[playernum])) / (TICKS_PER_SECOND50 * 1.f); | |||
| 32002 | stats[playernum]->setProficiencyUnsafe(proficiency, -999); | |||
| 32003 | real_t zeroValue = getBaseManaRegen(player, *(stats[playernum])) / (TICKS_PER_SECOND50 * 1.f); | |||
| 32004 | stats[playernum]->setProficiency(proficiency, skill); | |||
| 32005 | ||||
| 32006 | val = (100 * zeroValue / normalValue) - 100; | |||
| 32007 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 32008 | } | |||
| 32009 | else if ( tag == "CASTING_MP_REGEN_BONUS_INT" ) | |||
| 32010 | { | |||
| 32011 | val = 0.0; | |||
| 32012 | int stat = stats[playernum]->INT; | |||
| 32013 | real_t normalValue = getBaseManaRegen(player, *(stats[playernum])) / (TICKS_PER_SECOND50 * 1.f); | |||
| 32014 | stats[playernum]->INT = 0; | |||
| 32015 | real_t zeroValue = getBaseManaRegen(player, *(stats[playernum])) / (TICKS_PER_SECOND50 * 1.f); | |||
| 32016 | stats[playernum]->INT = stat; | |||
| 32017 | ||||
| 32018 | val = (100 * zeroValue / normalValue) - 100; | |||
| 32019 | snprintf(buf, sizeof(buf), rawValue.c_str(), val); | |||
| 32020 | } | |||
| 32021 | else if ( tag == "CASTING_BEGINNER" ) | |||
| 32022 | { | |||
| 32023 | if ( isSpellcasterBeginner(playernum, player) ) | |||
| 32024 | { | |||
| 32025 | snprintf(buf, sizeof(buf), rawValue.c_str(), Language::get(1314)); // yes | |||
| 32026 | } | |||
| 32027 | else | |||
| 32028 | { | |||
| 32029 | snprintf(buf, sizeof(buf), rawValue.c_str(), Language::get(1315)); // no | |||
| 32030 | } | |||
| 32031 | } | |||
| 32032 | else if ( tag == "CASTING_SPELLBOOK_FUMBLE" ) | |||
| 32033 | { | |||
| 32034 | int skillLVL = std::min(std::max(0, stats[playernum]->getModifiedProficiency(proficiency) + statGetINT(stats[playernum], player)), 100); | |||
| 32035 | skillLVL /= 20; | |||
| 32036 | std::string tierName = Language::get(4061); | |||
| 32037 | tierName += " "; | |||
| 32038 | if ( skillLVL <= 0 ) | |||
| 32039 | { | |||
| 32040 | tierName += "I"; | |||
| 32041 | } | |||
| 32042 | else if ( skillLVL == 1 ) | |||
| 32043 | { | |||
| 32044 | tierName += "II"; | |||
| 32045 | } | |||
| 32046 | else if ( skillLVL == 2 ) | |||
| 32047 | { | |||
| 32048 | tierName += "III"; | |||
| 32049 | } | |||
| 32050 | else if ( skillLVL == 3 ) | |||
| 32051 | { | |||
| 32052 | tierName += "IV"; | |||
| 32053 | } | |||
| 32054 | else if ( skillLVL == 4 ) | |||
| 32055 | { | |||
| 32056 | tierName += "V"; | |||
| 32057 | } | |||
| 32058 | else if ( skillLVL >= 5 ) | |||
| 32059 | { | |||
| 32060 | tierName += "VI"; | |||
| 32061 | } | |||
| 32062 | snprintf(buf, sizeof(buf), rawValue.c_str(), tierName.c_str()); | |||
| 32063 | } | |||
| 32064 | return buf; | |||
| 32065 | } | |||
| 32066 | else if ( proficiency == PRO_MAGIC ) | |||
| 32067 | { | |||
| 32068 | if ( tag == "MAGIC_CURRENT_TIER" ) | |||
| 32069 | { | |||
| 32070 | std::string tierName = Language::get(4061); | |||
| 32071 | int skillLVL = std::min(stats[playernum]->getModifiedProficiency(proficiency) + statGetINT(stats[playernum], player), 100); | |||
| 32072 | if ( skillLVL < 0 ) | |||
| 32073 | { | |||
| 32074 | tierName = Language::get(4057); // none | |||
| 32075 | } | |||
| 32076 | else | |||
| 32077 | { | |||
| 32078 | skillLVL /= 20; | |||
| 32079 | tierName += " "; | |||
| 32080 | if ( skillLVL == 0 ) | |||
| 32081 | { | |||
| 32082 | tierName += "I"; | |||
| 32083 | } | |||
| 32084 | else if ( skillLVL == 1 ) | |||
| 32085 | { | |||
| 32086 | tierName += "II"; | |||
| 32087 | } | |||
| 32088 | else if ( skillLVL == 2 ) | |||
| 32089 | { | |||
| 32090 | tierName += "III"; | |||
| 32091 | } | |||
| 32092 | else if ( skillLVL == 3 ) | |||
| 32093 | { | |||
| 32094 | tierName += "IV"; | |||
| 32095 | } | |||
| 32096 | else if ( skillLVL == 4 ) | |||
| 32097 | { | |||
| 32098 | tierName += "V"; | |||
| 32099 | } | |||
| 32100 | else if ( skillLVL >= 5 ) | |||
| 32101 | { | |||
| 32102 | tierName += "VI"; | |||
| 32103 | } | |||
| 32104 | } | |||
| 32105 | snprintf(buf, sizeof(buf), rawValue.c_str(), tierName.c_str()); | |||
| 32106 | } | |||
| 32107 | else if ( tag == "MAGIC_SPELLPOWER_TOTAL" ) | |||
| 32108 | { | |||
| 32109 | val = (getBonusFromCasterOfSpellElement(player, stats[playernum], nullptr, SPELL_NONE) * 100.0); | |||
| 32110 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 32111 | } | |||
| 32112 | else if ( tag == "MAGIC_SPELLPOWER_INT" ) | |||
| 32113 | { | |||
| 32114 | //val = (getBonusFromCasterOfSpellElement(player, stats[playernum], nullptr, SPELL_NONE) * 100.0); | |||
| 32115 | int INT = statGetINT(stats[playernum], players[playernum]->entity); | |||
| 32116 | real_t bonus = 0.0; | |||
| 32117 | if ( INT > 0 ) | |||
| 32118 | { | |||
| 32119 | bonus += INT / 100.0; | |||
| 32120 | } | |||
| 32121 | val = bonus * 100.0; | |||
| 32122 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 32123 | } | |||
| 32124 | else if ( tag == "MAGIC_SPELLPOWER_EQUIPMENT" ) | |||
| 32125 | { | |||
| 32126 | val = (getBonusFromCasterOfSpellElement(player, stats[playernum], nullptr, SPELL_NONE) * 100.0); | |||
| 32127 | int INT = statGetINT(stats[playernum], players[playernum]->entity); | |||
| 32128 | real_t bonus = 0.0; | |||
| 32129 | if ( INT > 0 ) | |||
| 32130 | { | |||
| 32131 | bonus += INT / 100.0; | |||
| 32132 | } | |||
| 32133 | val -= bonus * 100.0; | |||
| 32134 | snprintf(buf, sizeof(buf), rawValue.c_str(), (int)val); | |||
| 32135 | } | |||
| 32136 | else if ( tag == "MAGIC_CURRENT_TIER_SPELLS" ) | |||
| 32137 | { | |||
| 32138 | int skillLVL = std::min(stats[playernum]->getModifiedProficiency(proficiency) + statGetINT(stats[playernum], player), 100); | |||
| 32139 | if ( skillLVL >= 0 ) | |||
| 32140 | { | |||
| 32141 | skillLVL /= 20; | |||
| 32142 | } | |||
| 32143 | std::string magics = ""; | |||
| 32144 | for ( auto it = allGameSpells.begin(); it != allGameSpells.end(); ++it ) | |||
| 32145 | { | |||
| 32146 | auto spellEntry = *it; | |||
| 32147 | if ( spellEntry->ID == SPELL_WEAKNESS || spellEntry->ID == SPELL_GHOST_BOLT ) | |||
| 32148 | { | |||
| 32149 | continue; | |||
| 32150 | } | |||
| 32151 | if ( spellEntry && spellEntry->difficulty == (skillLVL * 20) ) | |||
| 32152 | { | |||
| 32153 | if ( magics != "" ) | |||
| 32154 | { | |||
| 32155 | magics += '\n'; | |||
| 32156 | } | |||
| 32157 | magics += "\x1E "; | |||
| 32158 | magics += spellEntry->getSpellName(); | |||
| 32159 | } | |||
| 32160 | } | |||
| 32161 | if ( magics == "" ) { magics = "-"; } | |||
| 32162 | snprintf(buf, sizeof(buf), rawValue.c_str(), magics.c_str()); | |||
| 32163 | } | |||
| 32164 | return buf; | |||
| 32165 | } | |||
| 32166 | ||||
| 32167 | return ""; | |||
| 32168 | } | |||
| 32169 | ||||
| 32170 | void Player::SkillSheet_t::selectSkill(int skill) | |||
| 32171 | { | |||
| 32172 | selectedSkill = skill; | |||
| 32173 | bSkillSheetEntryLoaded = false; | |||
| 32174 | openTick = ticks; | |||
| 32175 | resetSkillDisplay(); | |||
| 32176 | } | |||
| 32177 | ||||
| 32178 | //void positionSkillSheetBlitField(Field* f, Text* tex, SDL_Rect& pos, int yoff = 0) | |||
| 32179 | //{ | |||
| 32180 | // Font* actualFont = Font::get(f->getFont()); | |||
| 32181 | // int lines = std::max(1, tex->getNumTextLines()); | |||
| 32182 | // int fullH = lines * (actualFont->height(false) + actualFont->getOutline() * 2); | |||
| 32183 | // if ( f->getVJustify() == Field::justify_t::TOP ) | |||
| 32184 | // { | |||
| 32185 | // pos.y = pos.y + yoff + std::min(pos.h - fullH, 0); | |||
| 32186 | // } | |||
| 32187 | // else if ( f->getVJustify() == Field::justify_t::CENTER ) | |||
| 32188 | // { | |||
| 32189 | // pos.y = pos.y + yoff + (pos.h - fullH) / 2; | |||
| 32190 | // } | |||
| 32191 | // if ( f->getHJustify() == Field::justify_t::RIGHT ) | |||
| 32192 | // { | |||
| 32193 | // pos.x = pos.x + pos.w - tex->getWidth(); | |||
| 32194 | // } | |||
| 32195 | // else if ( f->getHJustify() == Field::justify_t::CENTER ) | |||
| 32196 | // { | |||
| 32197 | // pos.x = pos.x + pos.w / 2 - tex->getWidth() / 2; | |||
| 32198 | // } | |||
| 32199 | //} | |||
| 32200 | // | |||
| 32201 | //SDL_Surface* blitSkillSheet(Frame* skillsFrame) | |||
| 32202 | //{ | |||
| 32203 | // int player = skillsFrame->getOwner(); | |||
| 32204 | // SDL_Surface* sprite = SDL_CreateRGBSurface(0, skillsFrame->getSize().w, skillsFrame->getSize().h, 32, | |||
| 32205 | // 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); | |||
| 32206 | // | |||
| 32207 | // real_t opacity = 1.0; // skillsFrame->getOpacity() / 100.0 | |||
| 32208 | // | |||
| 32209 | // SDL_Rect totalPos = skillSheetEntryFrames[player].skillsFrame->getSize(); | |||
| 32210 | // /*for ( auto& img : skillSheetEntryFrames[player].entryFrameLeft->getImages() ) | |||
| 32211 | // { | |||
| 32212 | // if ( img->disabled ) { continue; } | |||
| 32213 | // if ( img->path == "" ) { continue; } | |||
| 32214 | // SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get(img->path.c_str())->getSurf()); | |||
| 32215 | // Uint8 r, g, b, a; | |||
| 32216 | // getColor(img->color, &r, &g, &b, &a); | |||
| 32217 | // SDL_SetSurfaceAlphaMod(srcSurf, a * opacity); | |||
| 32218 | // SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 32219 | // SDL_Rect pos = img->pos; | |||
| 32220 | // pos.x += totalPos.x; | |||
| 32221 | // pos.y += totalPos.y; | |||
| 32222 | // pos.x += skillSheetEntryFrames[player].entryFrameLeft->getSize().x; | |||
| 32223 | // pos.y += skillSheetEntryFrames[player].entryFrameLeft->getSize().y; | |||
| 32224 | // SDL_BlitScaled(srcSurf, nullptr, sprite, &pos); | |||
| 32225 | // } | |||
| 32226 | // | |||
| 32227 | // for ( auto& img : skillSheetEntryFrames[player].entryFrameRight->getImages() ) | |||
| 32228 | // { | |||
| 32229 | // if ( img->disabled ) { continue; } | |||
| 32230 | // if ( img->path == "" ) { continue; } | |||
| 32231 | // SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get(img->path.c_str())->getSurf()); | |||
| 32232 | // Uint8 r, g, b, a; | |||
| 32233 | // getColor(img->color, &r, &g, &b, &a); | |||
| 32234 | // SDL_SetSurfaceAlphaMod(srcSurf, a * opacity); | |||
| 32235 | // SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 32236 | // SDL_Rect pos = img->pos; | |||
| 32237 | // pos.x += totalPos.x; | |||
| 32238 | // pos.y += totalPos.y; | |||
| 32239 | // pos.x += skillSheetEntryFrames[player].entryFrameRight->getSize().x; | |||
| 32240 | // pos.y += skillSheetEntryFrames[player].entryFrameRight->getSize().y; | |||
| 32241 | // SDL_BlitScaled(srcSurf, nullptr, sprite, &pos); | |||
| 32242 | // }*/ | |||
| 32243 | // | |||
| 32244 | // for ( auto frame : skillSheetEntryFrames[player].skillsFrame->getFrames() ) | |||
| 32245 | // { | |||
| 32246 | // totalPos = skillSheetEntryFrames[player].skillsFrame->getSize(); | |||
| 32247 | // | |||
| 32248 | // totalPos.x += frame->getSize().x; | |||
| 32249 | // totalPos.y += frame->getSize().y; | |||
| 32250 | // for ( auto& img : frame->getImages() ) | |||
| 32251 | // { | |||
| 32252 | // if ( img->disabled ) { continue; } | |||
| 32253 | // if ( img->path == "" ) { continue; } | |||
| 32254 | // if ( img->ontop ) { continue; } | |||
| 32255 | // SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get(img->path.c_str())->getSurf()); | |||
| 32256 | // Uint8 r, g, b, a; | |||
| 32257 | // getColor(img->color, &r, &g, &b, &a); | |||
| 32258 | // SDL_SetSurfaceAlphaMod(srcSurf, a * opacity); | |||
| 32259 | // //SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 32260 | // SDL_Rect pos = img->pos; | |||
| 32261 | // pos.x += totalPos.x; | |||
| 32262 | // pos.y += totalPos.y; | |||
| 32263 | // SDL_BlitScaled(srcSurf, nullptr, sprite, &pos); | |||
| 32264 | // } | |||
| 32265 | // } | |||
| 32266 | // | |||
| 32267 | // for ( int i = 0; i < NUMPROFICIENCIES; ++i ) | |||
| 32268 | // { | |||
| 32269 | // Frame* frame = skillSheetEntryFrames[player].entryFrames[i]; | |||
| 32270 | // totalPos = skillSheetEntryFrames[player].skillsFrame->getSize(); | |||
| 32271 | // totalPos.x += frame->getSize().x; | |||
| 32272 | // if ( i >= 8 ) | |||
| 32273 | // { | |||
| 32274 | // totalPos.x += skillSheetEntryFrames[player].entryFrameLeft->getSize().x; | |||
| 32275 | // } | |||
| 32276 | // else | |||
| 32277 | // { | |||
| 32278 | // totalPos.x += skillSheetEntryFrames[player].entryFrameRight->getSize().x; | |||
| 32279 | // } | |||
| 32280 | // totalPos.y += frame->getSize().y; | |||
| 32281 | // if ( i >= 8 ) | |||
| 32282 | // { | |||
| 32283 | // totalPos.y += skillSheetEntryFrames[player].entryFrameLeft->getSize().y; | |||
| 32284 | // } | |||
| 32285 | // else | |||
| 32286 | // { | |||
| 32287 | // totalPos.y += skillSheetEntryFrames[player].entryFrameRight->getSize().y; | |||
| 32288 | // } | |||
| 32289 | // for ( auto img : frame->getImages() ) | |||
| 32290 | // { | |||
| 32291 | // if ( img->disabled ) { continue; } | |||
| 32292 | // if ( img->path == "" ) { continue; } | |||
| 32293 | // if ( img->ontop ) { continue; } | |||
| 32294 | // SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get(img->path.c_str())->getSurf()); | |||
| 32295 | // Uint8 r, g, b, a; | |||
| 32296 | // getColor(img->color, &r, &g, &b, &a); | |||
| 32297 | // SDL_SetSurfaceAlphaMod(srcSurf, a * opacity); | |||
| 32298 | // //SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 32299 | // SDL_Rect pos = img->pos; | |||
| 32300 | // pos.x += totalPos.x; | |||
| 32301 | // pos.y += totalPos.y; | |||
| 32302 | // SDL_BlitScaled(srcSurf, nullptr, sprite, &pos); | |||
| 32303 | // } | |||
| 32304 | // | |||
| 32305 | // for ( auto img : frame->getImages() ) | |||
| 32306 | // { | |||
| 32307 | // if ( img->disabled ) { continue; } | |||
| 32308 | // if ( img->path == "" ) { continue; } | |||
| 32309 | // if ( !img->ontop ) { continue; } | |||
| 32310 | // SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get(img->path.c_str())->getSurf()); | |||
| 32311 | // Uint8 r, g, b, a; | |||
| 32312 | // getColor(img->color, &r, &g, &b, &a); | |||
| 32313 | // SDL_SetSurfaceAlphaMod(srcSurf, a * opacity); | |||
| 32314 | // //SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 32315 | // SDL_Rect pos = img->pos; | |||
| 32316 | // pos.x += totalPos.x; | |||
| 32317 | // pos.y += totalPos.y; | |||
| 32318 | // SDL_BlitScaled(srcSurf, nullptr, sprite, &pos); | |||
| 32319 | // } | |||
| 32320 | // | |||
| 32321 | // for ( auto f : frame->getFields() ) | |||
| 32322 | // { | |||
| 32323 | // auto tex = f->getTextObject(); | |||
| 32324 | // SDL_Surface* srcSurf = const_cast<SDL_Surface*>(tex->getSurf()); | |||
| 32325 | // SDL_SetSurfaceAlphaMod(srcSurf, 255 * opacity); | |||
| 32326 | // //SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 32327 | // SDL_Rect pos = f->getSize(); | |||
| 32328 | // | |||
| 32329 | // positionSkillSheetBlitField(f, tex, pos); | |||
| 32330 | // | |||
| 32331 | // pos.x += totalPos.x; | |||
| 32332 | // pos.y += totalPos.y; | |||
| 32333 | // SDL_BlitSurface(srcSurf, nullptr, sprite, &pos); | |||
| 32334 | // } | |||
| 32335 | // } | |||
| 32336 | // | |||
| 32337 | // for ( auto frame : skillSheetEntryFrames[player].skillsFrame->getFrames() ) | |||
| 32338 | // { | |||
| 32339 | // totalPos = skillSheetEntryFrames[player].skillsFrame->getSize(); | |||
| 32340 | // | |||
| 32341 | // totalPos.x += frame->getSize().x; | |||
| 32342 | // totalPos.y += frame->getSize().y; | |||
| 32343 | // for ( auto& img : frame->getImages() ) | |||
| 32344 | // { | |||
| 32345 | // if ( img->disabled ) { continue; } | |||
| 32346 | // if ( img->path == "" ) { continue; } | |||
| 32347 | // if ( !img->ontop ) { continue; } | |||
| 32348 | // SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get(img->path.c_str())->getSurf()); | |||
| 32349 | // Uint8 r, g, b, a; | |||
| 32350 | // getColor(img->color, &r, &g, &b, &a); | |||
| 32351 | // SDL_SetSurfaceAlphaMod(srcSurf, a * opacity); | |||
| 32352 | // //SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 32353 | // SDL_Rect pos = img->pos; | |||
| 32354 | // pos.x += totalPos.x; | |||
| 32355 | // pos.y += totalPos.y; | |||
| 32356 | // SDL_BlitScaled(srcSurf, nullptr, sprite, &pos); | |||
| 32357 | // } | |||
| 32358 | // } | |||
| 32359 | // | |||
| 32360 | // //for ( auto img : skillsFrame->getImages() ) | |||
| 32361 | // //{ | |||
| 32362 | // // if ( img->disabled ) { continue; } | |||
| 32363 | // // if ( img->path == "" ) { continue; } | |||
| 32364 | // // SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get(img->path.c_str())->getSurf()); | |||
| 32365 | // // Uint8 r, g, b, a; | |||
| 32366 | // // getColor(img->color, &r, &g, &b, &a); | |||
| 32367 | // // SDL_SetSurfaceAlphaMod(srcSurf, a * opacity); | |||
| 32368 | // // //SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 32369 | // // SDL_Rect pos = img->pos; | |||
| 32370 | // // SDL_BlitScaled(srcSurf, nullptr, sprite, &pos); | |||
| 32371 | // //} | |||
| 32372 | // | |||
| 32373 | // for ( auto frame : skillsFrame->getFrames() ) | |||
| 32374 | // { | |||
| 32375 | // totalPos = skillSheetEntryFrames[player].skillsFrame->getSize(); | |||
| 32376 | // | |||
| 32377 | // for ( auto f : frame->getFields() ) | |||
| 32378 | // { | |||
| 32379 | // auto tex = f->getTextObject(); | |||
| 32380 | // SDL_Surface* srcSurf = const_cast<SDL_Surface*>(tex->getSurf()); | |||
| 32381 | // SDL_SetSurfaceAlphaMod(srcSurf, 255 * opacity); | |||
| 32382 | // //SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 32383 | // SDL_Rect pos = f->getSize(); | |||
| 32384 | // | |||
| 32385 | // positionSkillSheetBlitField(f, tex, pos); | |||
| 32386 | // | |||
| 32387 | // pos.x += totalPos.x; | |||
| 32388 | // pos.y += totalPos.y; | |||
| 32389 | // SDL_BlitSurface(srcSurf, nullptr, sprite, &pos); | |||
| 32390 | // } | |||
| 32391 | // } | |||
| 32392 | // | |||
| 32393 | // for ( auto frame : skillSheetEntryFrames[player].skillDescFrame->getFrames() ) | |||
| 32394 | // { | |||
| 32395 | // totalPos = skillSheetEntryFrames[player].skillsFrame->getSize(); | |||
| 32396 | // totalPos.x += skillSheetEntryFrames[player].skillDescFrame->getSize().x; | |||
| 32397 | // totalPos.y += skillSheetEntryFrames[player].skillDescFrame->getSize().y; | |||
| 32398 | // | |||
| 32399 | // totalPos.x += frame->getSize().x; | |||
| 32400 | // totalPos.y += frame->getSize().y; | |||
| 32401 | // for ( auto& img : frame->getImages() ) | |||
| 32402 | // { | |||
| 32403 | // if ( img->disabled ) { continue; } | |||
| 32404 | // if ( img->path == "" ) { continue; } | |||
| 32405 | // //if ( !img->ontop ) { continue; } | |||
| 32406 | // SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get(img->path.c_str())->getSurf()); | |||
| 32407 | // Uint8 r, g, b, a; | |||
| 32408 | // getColor(img->color, &r, &g, &b, &a); | |||
| 32409 | // SDL_SetSurfaceAlphaMod(srcSurf, a * opacity); | |||
| 32410 | // //SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 32411 | // SDL_Rect pos = img->pos; | |||
| 32412 | // pos.x += totalPos.x; | |||
| 32413 | // pos.y += totalPos.y; | |||
| 32414 | // SDL_BlitScaled(srcSurf, nullptr, sprite, &pos); | |||
| 32415 | // } | |||
| 32416 | // | |||
| 32417 | // for ( auto f : frame->getFields() ) | |||
| 32418 | // { | |||
| 32419 | // auto tex = f->getTextObject(); | |||
| 32420 | // SDL_Surface* srcSurf = const_cast<SDL_Surface*>(tex->getSurf()); | |||
| 32421 | // SDL_SetSurfaceAlphaMod(srcSurf, 255 * opacity); | |||
| 32422 | // //SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 32423 | // SDL_Rect pos = f->getSize(); | |||
| 32424 | // | |||
| 32425 | // positionSkillSheetBlitField(f, tex, pos); | |||
| 32426 | // | |||
| 32427 | // pos.x += totalPos.x; | |||
| 32428 | // pos.y += totalPos.y; | |||
| 32429 | // SDL_BlitSurface(srcSurf, nullptr, sprite, &pos); | |||
| 32430 | // } | |||
| 32431 | // } | |||
| 32432 | // | |||
| 32433 | // for ( auto frame : skillSheetEntryFrames[player].scrollAreaOuterFrame->getFrames() ) | |||
| 32434 | // { | |||
| 32435 | // totalPos = skillSheetEntryFrames[player].skillsFrame->getSize(); | |||
| 32436 | // totalPos.x += skillSheetEntryFrames[player].skillDescFrame->getSize().x; | |||
| 32437 | // totalPos.y += skillSheetEntryFrames[player].skillDescFrame->getSize().y; | |||
| 32438 | // totalPos.x += skillSheetEntryFrames[player].scrollAreaOuterFrame->getSize().x; | |||
| 32439 | // totalPos.y += skillSheetEntryFrames[player].scrollAreaOuterFrame->getSize().y; | |||
| 32440 | // | |||
| 32441 | // totalPos.x += frame->getSize().x; | |||
| 32442 | // totalPos.y += frame->getSize().y; | |||
| 32443 | // for ( auto& img : frame->getImages() ) | |||
| 32444 | // { | |||
| 32445 | // if ( img->disabled ) { continue; } | |||
| 32446 | // if ( img->path == "" ) { continue; } | |||
| 32447 | // //if ( !img->ontop ) { continue; } | |||
| 32448 | // SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get(img->path.c_str())->getSurf()); | |||
| 32449 | // Uint8 r, g, b, a; | |||
| 32450 | // getColor(img->color, &r, &g, &b, &a); | |||
| 32451 | // SDL_SetSurfaceAlphaMod(srcSurf, a * opacity); | |||
| 32452 | // //SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 32453 | // SDL_Rect pos = img->pos; | |||
| 32454 | // pos.x += totalPos.x; | |||
| 32455 | // pos.y += totalPos.y; | |||
| 32456 | // SDL_BlitScaled(srcSurf, nullptr, sprite, &pos); | |||
| 32457 | // } | |||
| 32458 | // | |||
| 32459 | // for ( auto f : frame->getFields() ) | |||
| 32460 | // { | |||
| 32461 | // if ( f->isDisabled() ) { continue; } | |||
| 32462 | // auto tex = f->getTextObject(); | |||
| 32463 | // SDL_Surface* srcSurf = const_cast<SDL_Surface*>(tex->getSurf()); | |||
| 32464 | // SDL_SetSurfaceAlphaMod(srcSurf, 255 * opacity); | |||
| 32465 | // //SDL_SetSurfaceBlendMode(srcSurf, SDL_BLENDMODE_NONE); | |||
| 32466 | // SDL_Rect pos = f->getSize(); | |||
| 32467 | // | |||
| 32468 | // if ( tex->getNumTextLines() > 1 ) | |||
| 32469 | // { | |||
| 32470 | // char* buf = (char*)malloc(f->getTextLen() + 1); | |||
| 32471 | // memcpy(buf, f->getText(), f->getTextLen() + 1); | |||
| 32472 | // | |||
| 32473 | // int yoff = 0; | |||
| 32474 | // int currentLine = -1; | |||
| 32475 | // char* nexttoken; | |||
| 32476 | // char* token = buf; | |||
| 32477 | // do { | |||
| 32478 | // ++currentLine; | |||
| 32479 | // nexttoken = Field::tokenize(token, "\n"); | |||
| 32480 | // | |||
| 32481 | // Text* text = Text::get(token, f->getFont(), f->getTextColor(), f->getOutlineColor()); | |||
| 32482 | // assert(text); | |||
| 32483 | // | |||
| 32484 | // positionSkillSheetBlitField(f, text, pos, yoff); | |||
| 32485 | // pos.x += totalPos.x; | |||
| 32486 | // pos.y += totalPos.y; | |||
| 32487 | // | |||
| 32488 | // srcSurf = const_cast<SDL_Surface*>(text->getSurf()); | |||
| 32489 | // SDL_SetSurfaceAlphaMod(srcSurf, 255 * opacity); | |||
| 32490 | // | |||
| 32491 | // SDL_Rect srcPos = pos; | |||
| 32492 | // srcPos.x = 0; | |||
| 32493 | // srcPos.y = 0; | |||
| 32494 | // if ( f->getSize().y + yoff + frame->getSize().y < 0 ) | |||
| 32495 | // { | |||
| 32496 | // int diff = f->getSize().y + yoff + frame->getSize().y; | |||
| 32497 | // srcPos.y -= diff; | |||
| 32498 | // pos.y -= diff; | |||
| 32499 | // } | |||
| 32500 | // else if ( f->getSize().y + yoff + text->getHeight() - (frame->getSize().h - frame->getSize().y) < 0 ) | |||
| 32501 | // { | |||
| 32502 | // int diff = f->getSize().y + yoff + text->getHeight() - (frame->getSize().h - frame->getSize().y); | |||
| 32503 | // srcPos.y -= diff; | |||
| 32504 | // pos.y -= diff; | |||
| 32505 | // } | |||
| 32506 | // SDL_BlitSurface(srcSurf, &srcPos, sprite, &pos); | |||
| 32507 | // | |||
| 32508 | // Font* actualFont = Font::get(f->getFont()); | |||
| 32509 | // yoff += actualFont->height(true); | |||
| 32510 | // pos = f->getSize(); | |||
| 32511 | // } while ( (token = nexttoken) != NULL ); | |||
| 32512 | // | |||
| 32513 | // free(buf); | |||
| 32514 | // } | |||
| 32515 | // else | |||
| 32516 | // { | |||
| 32517 | // positionSkillSheetBlitField(f, tex, pos); | |||
| 32518 | // pos.x += totalPos.x; | |||
| 32519 | // pos.y += totalPos.y; | |||
| 32520 | // SDL_BlitSurface(srcSurf, nullptr, sprite, &pos); | |||
| 32521 | // } | |||
| 32522 | // } | |||
| 32523 | // } | |||
| 32524 | // | |||
| 32525 | // return sprite; | |||
| 32526 | //} | |||
| 32527 | ||||
| 32528 | void buttonSkillsheetUpdateSelectorOnHighlight(const int player, Button* button) | |||
| 32529 | { | |||
| 32530 | if ( button->isHighlighted() ) | |||
| 32531 | { | |||
| 32532 | players[player]->GUI.setHoveringOverModuleButton(Player::GUI_t::MODULE_SKILLS_LIST); | |||
| 32533 | if ( players[player]->GUI.activeModule != Player::GUI_t::MODULE_SKILLS_LIST ) | |||
| 32534 | { | |||
| 32535 | players[player]->GUI.activateModule(Player::GUI_t::MODULE_SKILLS_LIST); | |||
| 32536 | } | |||
| 32537 | SDL_Rect pos = button->getAbsoluteSize(); | |||
| 32538 | // make sure to adjust absolute size to camera viewport | |||
| 32539 | pos.x -= players[player]->camera_virtualx1(); | |||
| 32540 | pos.y -= players[player]->camera_virtualy1(); | |||
| 32541 | players[player]->hud.setCursorDisabled(false); | |||
| 32542 | players[player]->hud.updateCursorAnimation(pos.x - 1, pos.y - 1, pos.w, pos.h, inputs.getVirtualMouse(player)->draw_cursor); | |||
| 32543 | } | |||
| 32544 | } | |||
| 32545 | ||||
| 32546 | void sliderSkillsheetUpdateSelectorOnHighlight(const int player, Slider* slider) | |||
| 32547 | { | |||
| 32548 | if ( slider->isHighlighted() ) | |||
| 32549 | { | |||
| 32550 | players[player]->GUI.setHoveringOverModuleButton(Player::GUI_t::MODULE_SKILLS_LIST); | |||
| 32551 | if ( players[player]->GUI.activeModule != Player::GUI_t::MODULE_SKILLS_LIST ) | |||
| 32552 | { | |||
| 32553 | players[player]->GUI.activateModule(Player::GUI_t::MODULE_SKILLS_LIST); | |||
| 32554 | } | |||
| 32555 | SDL_Rect pos = slider->getAbsoluteSize(); | |||
| 32556 | // make sure to adjust absolute size to camera viewport | |||
| 32557 | pos.x -= players[player]->camera_virtualx1(); | |||
| 32558 | pos.y -= players[player]->camera_virtualy1(); | |||
| 32559 | players[player]->hud.setCursorDisabled(false); | |||
| 32560 | players[player]->hud.updateCursorAnimation(pos.x - 1, pos.y - 1, pos.w, pos.h, inputs.getVirtualMouse(player)->draw_cursor); | |||
| 32561 | } | |||
| 32562 | } | |||
| 32563 | ||||
| 32564 | static ConsoleVariable<bool> cvar_skillsheet_optimise("/skillsheet_optimise", true); | |||
| 32565 | void Player::SkillSheet_t::processSkillSheet() | |||
| 32566 | { | |||
| 32567 | //DebugTimers.addTimePoint("skill 1", "start"); | |||
| 32568 | //DebugTimers.addTimePoint("skill", "start"); | |||
| 32569 | if ( !skillFrame ) | |||
| 32570 | { | |||
| 32571 | createSkillSheet(); | |||
| 32572 | } | |||
| 32573 | ||||
| 32574 | if ( !player.usingCommand() && Input::inputs[player.playernum].consumeBinaryToggle("Skill Sheet") | |||
| 32575 | && !gamePaused && players[player.playernum]->bControlEnabled ) | |||
| 32576 | { | |||
| 32577 | if ( !bSkillSheetOpen ) | |||
| 32578 | { | |||
| 32579 | openSkillSheet(); | |||
| 32580 | } | |||
| 32581 | else | |||
| 32582 | { | |||
| 32583 | closeSkillSheet(); | |||
| 32584 | Player::soundCancel(); | |||
| 32585 | } | |||
| 32586 | } | |||
| 32587 | ||||
| 32588 | auto oldSkillSlideAmount = skillSlideAmount; | |||
| 32589 | auto oldHighlightedSkill = highlightedSkill; | |||
| 32590 | ||||
| 32591 | if ( !bSkillSheetOpen ) | |||
| 32592 | { | |||
| 32593 | skillFrame->setDisabled(true); | |||
| 32594 | ||||
| 32595 | auto innerFrame = skillFrame->findFrame("skills frame"); | |||
| 32596 | SDL_Rect pos = innerFrame->getSize(); | |||
| 32597 | skillsFadeInAnimationY = 0.0; | |||
| 32598 | pos.y = -pos.h; | |||
| 32599 | innerFrame->setSize(pos); | |||
| 32600 | ||||
| 32601 | auto fade = skillFrame->findImage("fade img"); | |||
| 32602 | Uint8 r, g, b, a; | |||
| 32603 | getColor(fade->color, &r, &g, &b, &a); | |||
| 32604 | a = 0; | |||
| 32605 | fade->color = makeColor( r, g, b, a); | |||
| 32606 | fade->disabled = true; | |||
| 32607 | return; | |||
| 32608 | } | |||
| 32609 | ||||
| 32610 | bool reblitFrame = false; | |||
| 32611 | ||||
| 32612 | skillFrame->setDisabled(false); | |||
| 32613 | skillFrame->setSize(SDL_Rect{ players[player.playernum]->camera_virtualx1(), | |||
| 32614 | players[player.playernum]->camera_virtualy1(), | |||
| 32615 | players[player.playernum]->camera_virtualWidth(), | |||
| 32616 | players[player.playernum]->camera_virtualHeight() }); | |||
| 32617 | ||||
| 32618 | bool oldCompactViewVal = bUseCompactSkillsView; | |||
| 32619 | bool oldSlideWindowsOnly = bSlideWindowsOnly; | |||
| 32620 | if ( splitscreen && (player.bUseCompactGUIHeight() || player.bUseCompactGUIWidth()) ) | |||
| 32621 | { | |||
| 32622 | // use compact view. | |||
| 32623 | if ( player.bUseCompactGUIWidth() && !player.bUseCompactGUIHeight() ) | |||
| 32624 | { | |||
| 32625 | bSlideWindowsOnly = true; // 2 player vertical splitscreen, slide but don't use compact view | |||
| 32626 | bUseCompactSkillsView = false; | |||
| 32627 | } | |||
| 32628 | else | |||
| 32629 | { | |||
| 32630 | bUseCompactSkillsView = true; | |||
| 32631 | bSlideWindowsOnly = false; | |||
| 32632 | } | |||
| 32633 | } | |||
| 32634 | else | |||
| 32635 | { | |||
| 32636 | bUseCompactSkillsView = false; | |||
| 32637 | bSlideWindowsOnly = false; | |||
| 32638 | } | |||
| 32639 | if ( (oldCompactViewVal != bUseCompactSkillsView && bUseCompactSkillsView) | |||
| 32640 | || (oldSlideWindowsOnly != bSlideWindowsOnly && bSlideWindowsOnly) ) | |||
| 32641 | { | |||
| 32642 | if ( selectedSkill >= 8 ) | |||
| 32643 | { | |||
| 32644 | skillSlideAmount = 1.0; | |||
| 32645 | skillSlideDirection = 1; | |||
| 32646 | } | |||
| 32647 | else | |||
| 32648 | { | |||
| 32649 | skillSlideAmount = -1.0; | |||
| 32650 | skillSlideDirection = -1; | |||
| 32651 | } | |||
| 32652 | } | |||
| 32653 | if ( !bUseCompactSkillsView && !bSlideWindowsOnly || (bUseCompactSkillsView && !player.bUseCompactGUIWidth()) ) | |||
| 32654 | { | |||
| 32655 | skillSlideAmount = 0.0; | |||
| 32656 | skillSlideDirection = 0; | |||
| 32657 | } | |||
| 32658 | ||||
| 32659 | auto innerFrame = skillSheetEntryFrames[player.playernum].skillsFrame; | |||
| 32660 | SDL_Rect sheetSize = innerFrame->getSize(); | |||
| 32661 | Frame* allSkillEntriesLeft = skillSheetEntryFrames[player.playernum].entryFrameLeft; | |||
| 32662 | Frame* allSkillEntriesRight = skillSheetEntryFrames[player.playernum].entryFrameRight; | |||
| 32663 | auto leftWingImg = allSkillEntriesLeft->findImage("bg wing left"); | |||
| 32664 | auto rightWingImg = allSkillEntriesRight->findImage("bg wing right"); | |||
| 32665 | auto skillDescriptionFrame = skillSheetEntryFrames[player.playernum].skillDescFrame; | |||
| 32666 | auto bgImgFrame = skillSheetEntryFrames[player.playernum].skillBgImgsFrame; | |||
| 32667 | auto scrollAreaOuterFrame = skillSheetEntryFrames[player.playernum].scrollAreaOuterFrame; | |||
| 32668 | auto scrollArea = skillSheetEntryFrames[player.playernum].scrollArea; | |||
| 32669 | SDL_Rect scrollOuterFramePos = scrollAreaOuterFrame->getSize(); | |||
| 32670 | SDL_Rect scrollAreaPos = scrollArea->getSize(); | |||
| 32671 | ||||
| 32672 | real_t slideTravelDistance = 52; | |||
| 32673 | int compactViewWidthOffset = (skillSlideDirection != 0 ? 104: 0); | |||
| 32674 | { | |||
| 32675 | // dynamic width/height adjustments of outer containers | |||
| 32676 | sheetSize.h = std::max(0, std::min(skillFrame->getSize().h - 8, | |||
| 32677 | (int)(404 + (bUseCompactSkillsView ? windowCompactHeightScaleY : windowHeightScaleY) * 80))); | |||
| 32678 | sheetSize.w = std::max(0, std::min(skillFrame->getSize().w - 8, | |||
| 32679 | (int)(684 + (bUseCompactSkillsView ? windowCompactHeightScaleX : windowHeightScaleX) * 80))); | |||
| 32680 | if ( player.bUseCompactGUIHeight() && !player.bUseCompactGUIWidth() ) | |||
| 32681 | { | |||
| 32682 | sheetSize.w += 12; // some adjustment to match 4 player as it's bigger | |||
| 32683 | } | |||
| 32684 | innerFrame->setSize(sheetSize); | |||
| 32685 | ||||
| 32686 | SDL_Rect skillDescPos = skillDescriptionFrame->getSize(); | |||
| 32687 | skillDescPos.h = innerFrame->getSize().h - skillDescPos.y - 16; | |||
| 32688 | skillDescPos.w = innerFrame->getSize().w + compactViewWidthOffset - allSkillEntriesLeft->getSize().w - allSkillEntriesRight->getSize().w; | |||
| 32689 | int xMove = innerFrame->getSize().w / 2 - skillDescPos.w / 2; | |||
| 32690 | if ( skillSlideDirection != 0 ) | |||
| 32691 | { | |||
| 32692 | xMove += (skillSlideAmount) * slideTravelDistance; | |||
| 32693 | } | |||
| 32694 | if ( xMove != skillDescPos.x ) | |||
| 32695 | { | |||
| 32696 | reblitFrame = true; | |||
| 32697 | } | |||
| 32698 | skillDescPos.x = xMove; | |||
| 32699 | skillDescriptionFrame->setSize(skillDescPos); | |||
| 32700 | ||||
| 32701 | scrollOuterFramePos.h = skillDescPos.h - 4; | |||
| 32702 | ||||
| 32703 | auto leftWingPos = allSkillEntriesLeft->getSize(); | |||
| 32704 | auto rightWingPos = allSkillEntriesRight->getSize(); | |||
| 32705 | ||||
| 32706 | leftWingPos.x = 0; | |||
| 32707 | rightWingPos.x = innerFrame->getSize().w - rightWingPos.w; | |||
| 32708 | leftWingPos.y = std::max(0, innerFrame->getSize().h / 2 - leftWingPos.h / 2); | |||
| 32709 | rightWingPos.y = std::max(0, innerFrame->getSize().h / 2 - rightWingPos.h / 2); | |||
| 32710 | allSkillEntriesLeft->setSize(leftWingPos); | |||
| 32711 | allSkillEntriesRight->setSize(rightWingPos); | |||
| 32712 | ||||
| 32713 | auto leftWingAllSkillsImg = allSkillEntriesLeft->findImage("bg wing all skills left"); | |||
| 32714 | leftWingAllSkillsImg->ontop = true; | |||
| 32715 | auto rightWingAllSkillsImg = allSkillEntriesRight->findImage("bg wing all skills right"); | |||
| 32716 | rightWingAllSkillsImg->ontop = true; | |||
| 32717 | int index = 0; | |||
| 32718 | std::string leftBinary = "00000000"; | |||
| 32719 | std::string rightBinary = "00000000"; | |||
| 32720 | for ( auto& skillEntry : skillSheetData.skillEntries ) | |||
| 32721 | { | |||
| 32722 | if ( index >= 8 ) | |||
| 32723 | { | |||
| 32724 | if ( stats[player.playernum]->getModifiedProficiency(skillEntry.skillId) >= SKILL_LEVEL_LEGENDARY ) | |||
| 32725 | { | |||
| 32726 | leftBinary[7 - (index - 8)] = '1'; | |||
| 32727 | } | |||
| 32728 | } | |||
| 32729 | else | |||
| 32730 | { | |||
| 32731 | if ( stats[player.playernum]->getModifiedProficiency(skillEntry.skillId) >= SKILL_LEVEL_LEGENDARY ) | |||
| 32732 | { | |||
| 32733 | rightBinary[7 - index] = '1'; | |||
| 32734 | } | |||
| 32735 | } | |||
| 32736 | ++index; | |||
| 32737 | } | |||
| 32738 | if ( bUseCompactSkillsView ) | |||
| 32739 | { | |||
| 32740 | leftWingImg->path = "*#images/ui/SkillSheet/UI_Skills_Window_LeftCompact_04.png"; | |||
| 32741 | rightWingImg->path = "*#images/ui/SkillSheet/UI_Skills_Window_RightCompact_04.png"; | |||
| 32742 | ||||
| 32743 | leftWingAllSkillsImg->path = "*#images/ui/SkillSheet/Icons2/UI_Skills_Left_Comp_" + leftBinary + ".png"; | |||
| 32744 | rightWingAllSkillsImg->path = "*#images/ui/SkillSheet/Icons2/UI_Skills_Right_Comp_" + rightBinary + ".png"; | |||
| 32745 | } | |||
| 32746 | else | |||
| 32747 | { | |||
| 32748 | leftWingImg->path = "*#images/ui/SkillSheet/UI_Skills_Window_Left_04.png"; | |||
| 32749 | rightWingImg->path = "*#images/ui/SkillSheet/UI_Skills_Window_Right_04.png"; | |||
| 32750 | ||||
| 32751 | leftWingAllSkillsImg->path = "*#images/ui/SkillSheet/Icons2/UI_Skills_Left_Full_" + leftBinary + ".png"; | |||
| 32752 | rightWingAllSkillsImg->path = "*#images/ui/SkillSheet/Icons2/UI_Skills_Right_Full_" + rightBinary + ".png"; | |||
| 32753 | } | |||
| 32754 | if ( auto imgGet = Image::get(leftWingAllSkillsImg->path.c_str()) ) | |||
| 32755 | { | |||
| 32756 | if ( bUseCompactSkillsView ) | |||
| 32757 | { | |||
| 32758 | leftWingAllSkillsImg->pos.x = 6 + leftWingImg->pos.x; | |||
| 32759 | leftWingAllSkillsImg->pos.y = 22 + leftWingImg->pos.y; | |||
| 32760 | } | |||
| 32761 | else | |||
| 32762 | { | |||
| 32763 | leftWingAllSkillsImg->pos.x = 6 + leftWingImg->pos.x; | |||
| 32764 | leftWingAllSkillsImg->pos.y = 32 + leftWingImg->pos.y; | |||
| 32765 | } | |||
| 32766 | leftWingAllSkillsImg->pos.w = imgGet->getWidth(); | |||
| 32767 | leftWingAllSkillsImg->pos.h = imgGet->getHeight(); | |||
| 32768 | } | |||
| 32769 | if ( auto imgGet = Image::get(rightWingAllSkillsImg->path.c_str()) ) | |||
| 32770 | { | |||
| 32771 | if ( bUseCompactSkillsView ) | |||
| 32772 | { | |||
| 32773 | rightWingAllSkillsImg->pos.x = 152 + rightWingImg->pos.x; | |||
| 32774 | rightWingAllSkillsImg->pos.y = 22 + rightWingImg->pos.y; | |||
| 32775 | } | |||
| 32776 | else | |||
| 32777 | { | |||
| 32778 | rightWingAllSkillsImg->pos.x = 152 + rightWingImg->pos.x; | |||
| 32779 | rightWingAllSkillsImg->pos.y = 32 + rightWingImg->pos.y; | |||
| 32780 | } | |||
| 32781 | rightWingAllSkillsImg->pos.w = imgGet->getWidth(); | |||
| 32782 | rightWingAllSkillsImg->pos.h = imgGet->getHeight(); | |||
| 32783 | } | |||
| 32784 | leftWingImg->pos.h = Image::get(leftWingImg->path.c_str())->getHeight(); | |||
| 32785 | rightWingImg->pos.h = Image::get(rightWingImg->path.c_str())->getHeight(); | |||
| 32786 | } | |||
| 32787 | { | |||
| 32788 | // dynamic main panel width/height background image adjustment | |||
| 32789 | SDL_Rect bgImgFramePos = bgImgFrame->getSize(); | |||
| 32790 | int backgroundWidth = skillDescriptionFrame->getSize().w; | |||
| 32791 | int backgroundHeight = innerFrame->getSize().h; | |||
| 32792 | ||||
| 32793 | auto flourishTop = bgImgFrame->findImage("flourish top"); | |||
| 32794 | flourishTop->pos.x = bgImgFramePos.w / 2 - flourishTop->pos.w / 2; | |||
| 32795 | auto flourishBottom = bgImgFrame->findImage("flourish bottom"); | |||
| 32796 | flourishBottom->pos.x = bgImgFramePos.w / 2 - flourishBottom->pos.w / 2; | |||
| 32797 | flourishBottom->pos.y = backgroundHeight - flourishBottom->pos.h; | |||
| 32798 | flourishTop->disabled = true; | |||
| 32799 | flourishBottom->disabled = true; | |||
| 32800 | ||||
| 32801 | ||||
| 32802 | bgImgFramePos.x = innerFrame->getSize().w / 2 - backgroundWidth / 2; | |||
| 32803 | if ( skillSlideDirection != 0 ) | |||
| 32804 | { | |||
| 32805 | bgImgFramePos.x += (skillSlideAmount) * slideTravelDistance; | |||
| 32806 | } | |||
| 32807 | bgImgFramePos.y = 0; | |||
| 32808 | bgImgFramePos.w = backgroundWidth; | |||
| 32809 | bgImgFramePos.h = backgroundHeight; | |||
| 32810 | bgImgFrame->setSize(bgImgFramePos); | |||
| 32811 | ||||
| 32812 | if ( backgroundWidth == 480 && backgroundHeight == 500 && *cvar_skillsheet_optimise ) | |||
| 32813 | { | |||
| 32814 | for ( auto img : bgImgFrame->getImages() ) | |||
| 32815 | { | |||
| 32816 | img->disabled = true; | |||
| 32817 | } | |||
| 32818 | auto mm = bgImgFrame->findImage(skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 32819 | mm->pos.x = 0; | |||
| 32820 | mm->pos.y = 0; | |||
| 32821 | mm->pos.w = backgroundWidth; | |||
| 32822 | mm->pos.h = backgroundHeight; | |||
| 32823 | mm->color = makeColorRGB(255, 255, 255); | |||
| 32824 | mm->path = ("*#images/ui/SkillSheet/UI_Skills_Full_480x500.png"); | |||
| 32825 | mm->disabled = false; | |||
| 32826 | } | |||
| 32827 | else if ( backgroundWidth == 360 && backgroundHeight == 352 && *cvar_skillsheet_optimise ) | |||
| 32828 | { | |||
| 32829 | for ( auto img : bgImgFrame->getImages() ) | |||
| 32830 | { | |||
| 32831 | img->disabled = true; | |||
| 32832 | } | |||
| 32833 | auto mm = bgImgFrame->findImage(skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 32834 | mm->pos.x = 0; | |||
| 32835 | mm->pos.y = 0; | |||
| 32836 | mm->pos.w = backgroundWidth; | |||
| 32837 | mm->pos.h = backgroundHeight; | |||
| 32838 | mm->color = makeColorRGB(255, 255, 255); | |||
| 32839 | mm->path = ("*#images/ui/SkillSheet/UI_Skills_Full_360x352.png"); | |||
| 32840 | mm->disabled = false; | |||
| 32841 | } | |||
| 32842 | else if ( backgroundWidth == 372 && backgroundHeight == 352 && *cvar_skillsheet_optimise ) | |||
| 32843 | { | |||
| 32844 | for ( auto img : bgImgFrame->getImages() ) | |||
| 32845 | { | |||
| 32846 | img->disabled = true; | |||
| 32847 | } | |||
| 32848 | auto mm = bgImgFrame->findImage(skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 32849 | mm->pos.x = 0; | |||
| 32850 | mm->pos.y = 0; | |||
| 32851 | mm->pos.w = backgroundWidth; | |||
| 32852 | mm->pos.h = backgroundHeight; | |||
| 32853 | mm->color = makeColorRGB(255, 255, 255); | |||
| 32854 | mm->path = ("*#images/ui/SkillSheet/UI_Skills_Full_372x352.png"); | |||
| 32855 | mm->disabled = false; | |||
| 32856 | } | |||
| 32857 | else if ( backgroundWidth == 372 && backgroundHeight == 500 && *cvar_skillsheet_optimise ) | |||
| 32858 | { | |||
| 32859 | for ( auto img : bgImgFrame->getImages() ) | |||
| 32860 | { | |||
| 32861 | img->disabled = true; | |||
| 32862 | } | |||
| 32863 | auto mm = bgImgFrame->findImage(skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 32864 | mm->pos.x = 0; | |||
| 32865 | mm->pos.y = 0; | |||
| 32866 | mm->pos.w = backgroundWidth; | |||
| 32867 | mm->pos.h = backgroundHeight; | |||
| 32868 | mm->color = makeColorRGB(255, 255, 255); | |||
| 32869 | mm->path = ("*#images/ui/SkillSheet/UI_Skills_Full_372x500.png"); | |||
| 32870 | mm->disabled = false; | |||
| 32871 | } | |||
| 32872 | else | |||
| 32873 | { | |||
| 32874 | for ( auto img : bgImgFrame->getImages() ) | |||
| 32875 | { | |||
| 32876 | img->disabled = false; | |||
| 32877 | } | |||
| 32878 | flourishTop->disabled = false; | |||
| 32879 | flourishBottom->disabled = false; | |||
| 32880 | auto mm = bgImgFrame->findImage(skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 32881 | mm->path = "images/system/white.png"; | |||
| 32882 | mm->color = makeColor(0, 0, 0, 255); | |||
| 32883 | imageResizeToContainer9x9(bgImgFrame, SDL_Rect{0, 12, backgroundWidth, backgroundHeight - 6 }, skillsheetEffectBackgroundImages); | |||
| 32884 | } | |||
| 32885 | } | |||
| 32886 | ||||
| 32887 | //DebugTimers.addTimePoint("skill", "post resize"); | |||
| 32888 | ||||
| 32889 | sheetSize.x = skillFrame->getSize().w / 2 - sheetSize.w / 2; | |||
| 32890 | ||||
| 32891 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 32892 | real_t setpointDiffX = fpsScale * std::max(.01, (1.0 - skillsFadeInAnimationY)) / 3.0; | |||
| 32893 | skillsFadeInAnimationY += setpointDiffX; | |||
| 32894 | skillsFadeInAnimationY = std::min(1.0, skillsFadeInAnimationY); | |||
| 32895 | ||||
| 32896 | auto fade = skillFrame->findImage("fade img"); | |||
| 32897 | Uint8 r, g, b, a; | |||
| 32898 | getColor(fade->color, &r, &g, &b, &a); | |||
| 32899 | a = 128 * skillsFadeInAnimationY; | |||
| 32900 | fade->color = makeColor( r, g, b, a); | |||
| 32901 | fade->disabled = false; | |||
| 32902 | fade->pos.w = skillFrame->getSize().w; | |||
| 32903 | fade->pos.h = skillFrame->getSize().h; | |||
| 32904 | ||||
| 32905 | int baseY = (skillFrame->getSize().h / 2 - sheetSize.h / 2); | |||
| 32906 | sheetSize.y = -sheetSize.h + skillsFadeInAnimationY * (baseY + sheetSize.h); | |||
| 32907 | innerFrame->setOpacity(pow(skillsFadeInAnimationY, 2) * 100.0); | |||
| 32908 | innerFrame->setSize(sheetSize); | |||
| 32909 | ||||
| 32910 | auto slider = skillDescriptionFrame->findSlider("skill slider"); | |||
| 32911 | if ( slider->isSelected() ) | |||
| 32912 | { | |||
| 32913 | slider->deselect(); | |||
| 32914 | } | |||
| 32915 | //slider->setHideSelectors(false); | |||
| 32916 | bool sliderDisabled = slider->isDisabled(); | |||
| 32917 | ||||
| 32918 | auto titleText = innerFrame->findField("skill title txt"); | |||
| 32919 | SDL_Rect titleTextPos = titleText->getSize(); | |||
| 32920 | titleTextPos.x = skillDescriptionFrame->getSize().x + skillDescriptionFrame->getSize().w / 2 - titleTextPos.w / 2; | |||
| 32921 | titleText->setSize(titleTextPos); | |||
| 32922 | ||||
| 32923 | if ( skillSlideDirection != 0 ) | |||
| 32924 | { | |||
| 32925 | const real_t fpsScale = (getFPSScale(144.0)); // ported from 144Hz | |||
| 32926 | real_t setpointDiff = std::max(0.1, 1.0 - abs(skillSlideAmount)); | |||
| 32927 | skillSlideAmount += fpsScale * (setpointDiff / 5.0) * skillSlideDirection; | |||
| 32928 | if ( skillSlideAmount < -1.0 ) | |||
| 32929 | { | |||
| 32930 | skillSlideAmount = -1.0; | |||
| 32931 | } | |||
| 32932 | if ( skillSlideAmount > 1.0 ) | |||
| 32933 | { | |||
| 32934 | skillSlideAmount = 1.0; | |||
| 32935 | } | |||
| 32936 | } | |||
| 32937 | ||||
| 32938 | if ( oldSkillSlideAmount != skillSlideAmount ) | |||
| 32939 | { | |||
| 32940 | reblitFrame = true; | |||
| 32941 | } | |||
| 32942 | ||||
| 32943 | int lowestSkillEntryY = 0; | |||
| 32944 | bool dpad_moved = false; | |||
| 32945 | if ( ::inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 32946 | { | |||
| 32947 | highlightedSkill = -1; // if using mouse, clear out the highlighted skill data to be updated below | |||
| 32948 | } | |||
| 32949 | int defaultHighlightedSkill = 0; | |||
| 32950 | if ( selectedSkill >= 0 && selectedSkill < NUMPROFICIENCIES ) | |||
| 32951 | { | |||
| 32952 | defaultHighlightedSkill = selectedSkill; | |||
| 32953 | } | |||
| 32954 | bool closeSheetAction = false; | |||
| 32955 | if ( player.GUI.activeModule == player.GUI.MODULE_SKILLS_LIST ) | |||
| 32956 | { | |||
| 32957 | if ( Input::inputs[player.playernum].binaryToggle("MenuUp") | |||
| 32958 | && player.bControlEnabled && !gamePaused && !player.usingCommand() ) | |||
| 32959 | { | |||
| 32960 | dpad_moved = true; | |||
| 32961 | Input::inputs[player.playernum].consumeBinaryToggle("MenuUp"); | |||
| 32962 | if ( highlightedSkill < 0 || highlightedSkill >= NUMPROFICIENCIES ) | |||
| 32963 | { | |||
| 32964 | highlightedSkill = defaultHighlightedSkill; | |||
| 32965 | } | |||
| 32966 | else if ( highlightedSkill < NUMPROFICIENCIES / 2 ) | |||
| 32967 | { | |||
| 32968 | --highlightedSkill; | |||
| 32969 | if ( highlightedSkill < 0 ) | |||
| 32970 | { | |||
| 32971 | highlightedSkill = (NUMPROFICIENCIES / 2) - 1; | |||
| 32972 | } | |||
| 32973 | } | |||
| 32974 | else | |||
| 32975 | { | |||
| 32976 | --highlightedSkill; | |||
| 32977 | if ( highlightedSkill < NUMPROFICIENCIES / 2 ) | |||
| 32978 | { | |||
| 32979 | highlightedSkill = NUMPROFICIENCIES - 1; | |||
| 32980 | } | |||
| 32981 | } | |||
| 32982 | if ( selectedSkill != highlightedSkill ) | |||
| 32983 | { | |||
| 32984 | selectSkill(highlightedSkill); | |||
| 32985 | } | |||
| 32986 | } | |||
| 32987 | if ( Input::inputs[player.playernum].binaryToggle("MenuDown") | |||
| 32988 | && player.bControlEnabled && !gamePaused && !player.usingCommand() ) | |||
| 32989 | { | |||
| 32990 | dpad_moved = true; | |||
| 32991 | Input::inputs[player.playernum].consumeBinaryToggle("MenuDown"); | |||
| 32992 | if ( highlightedSkill < 0 || highlightedSkill >= NUMPROFICIENCIES ) | |||
| 32993 | { | |||
| 32994 | highlightedSkill = defaultHighlightedSkill; | |||
| 32995 | } | |||
| 32996 | else if ( highlightedSkill < (NUMPROFICIENCIES / 2) ) | |||
| 32997 | { | |||
| 32998 | ++highlightedSkill; | |||
| 32999 | if ( highlightedSkill >= NUMPROFICIENCIES / 2 ) | |||
| 33000 | { | |||
| 33001 | highlightedSkill = 0; | |||
| 33002 | } | |||
| 33003 | } | |||
| 33004 | else | |||
| 33005 | { | |||
| 33006 | ++highlightedSkill; | |||
| 33007 | if ( highlightedSkill >= NUMPROFICIENCIES ) | |||
| 33008 | { | |||
| 33009 | highlightedSkill = (NUMPROFICIENCIES / 2); | |||
| 33010 | } | |||
| 33011 | } | |||
| 33012 | if ( selectedSkill != highlightedSkill ) | |||
| 33013 | { | |||
| 33014 | selectSkill(highlightedSkill); | |||
| 33015 | } | |||
| 33016 | } | |||
| 33017 | if ( Input::inputs[player.playernum].binaryToggle("MenuLeft") | |||
| 33018 | && player.bControlEnabled && !gamePaused && !player.usingCommand() ) | |||
| 33019 | { | |||
| 33020 | dpad_moved = true; | |||
| 33021 | Input::inputs[player.playernum].consumeBinaryToggle("MenuLeft"); | |||
| 33022 | if ( highlightedSkill < 0 || highlightedSkill >= NUMPROFICIENCIES ) | |||
| 33023 | { | |||
| 33024 | highlightedSkill = defaultHighlightedSkill; | |||
| 33025 | } | |||
| 33026 | else if ( highlightedSkill < NUMPROFICIENCIES / 2 ) | |||
| 33027 | { | |||
| 33028 | highlightedSkill += NUMPROFICIENCIES / 2; | |||
| 33029 | } | |||
| 33030 | else | |||
| 33031 | { | |||
| 33032 | highlightedSkill -= NUMPROFICIENCIES / 2; | |||
| 33033 | } | |||
| 33034 | if ( selectedSkill != highlightedSkill ) | |||
| 33035 | { | |||
| 33036 | selectSkill(highlightedSkill); | |||
| 33037 | } | |||
| 33038 | } | |||
| 33039 | if ( Input::inputs[player.playernum].binaryToggle("MenuRight") | |||
| 33040 | && player.bControlEnabled && !gamePaused && !player.usingCommand() ) | |||
| 33041 | { | |||
| 33042 | dpad_moved = true; | |||
| 33043 | Input::inputs[player.playernum].consumeBinaryToggle("MenuRight"); | |||
| 33044 | if ( highlightedSkill < 0 || highlightedSkill >= NUMPROFICIENCIES ) | |||
| 33045 | { | |||
| 33046 | highlightedSkill = defaultHighlightedSkill; | |||
| 33047 | } | |||
| 33048 | else if ( highlightedSkill < NUMPROFICIENCIES / 2 ) | |||
| 33049 | { | |||
| 33050 | highlightedSkill += NUMPROFICIENCIES / 2; | |||
| 33051 | } | |||
| 33052 | else | |||
| 33053 | { | |||
| 33054 | highlightedSkill -= NUMPROFICIENCIES / 2; | |||
| 33055 | } | |||
| 33056 | if ( selectedSkill != highlightedSkill ) | |||
| 33057 | { | |||
| 33058 | selectSkill(highlightedSkill); | |||
| 33059 | } | |||
| 33060 | } | |||
| 33061 | ||||
| 33062 | if ( dpad_moved ) | |||
| 33063 | { | |||
| 33064 | if ( skillSlideDirection != 0 ) | |||
| 33065 | { | |||
| 33066 | if ( highlightedSkill >= 8 ) | |||
| 33067 | { | |||
| 33068 | skillSlideDirection = 1; | |||
| 33069 | } | |||
| 33070 | else | |||
| 33071 | { | |||
| 33072 | skillSlideDirection = -1; | |||
| 33073 | } | |||
| 33074 | } | |||
| 33075 | inputs.getVirtualMouse(player.playernum)->draw_cursor = false; | |||
| 33076 | Player::soundMovement(); | |||
| 33077 | } | |||
| 33078 | if ( Input::inputs[player.playernum].binaryToggle("MenuCancel") | |||
| 33079 | && player.bControlEnabled && !gamePaused && !player.usingCommand() ) | |||
| 33080 | { | |||
| 33081 | Input::inputs[player.playernum].consumeBinaryToggle("MenuCancel"); | |||
| 33082 | closeSheetAction = true; | |||
| 33083 | } | |||
| 33084 | } | |||
| 33085 | bool mouseClickedOutOfBounds = false; | |||
| 33086 | if ( inputs.bPlayerUsingKeyboardControl(player.playernum) && Input::inputs[player.playernum].binaryToggle("MenuLeftClick") ) | |||
| 33087 | { | |||
| 33088 | mouseClickedOutOfBounds = true; | |||
| 33089 | } | |||
| 33090 | ||||
| 33091 | //DebugTimers.addTimePoint("skill", "post inputs"); | |||
| 33092 | ||||
| 33093 | if ( stats[player.playernum] && skillSheetData.skillEntries.size() > 0 ) | |||
| 33094 | { | |||
| 33095 | bool skillDescAreaCapturesMouse = bgImgFrame->capturesMouse(); | |||
| 33096 | if ( skillDescAreaCapturesMouse ) { mouseClickedOutOfBounds = false; } | |||
| 33097 | const int skillEntryStartY = bUseCompactSkillsView ? 28 : 38; | |||
| 33098 | const int entryHeight = bUseCompactSkillsView ? 36 : 40; | |||
| 33099 | SDL_Rect entryResizePos{ 0, skillEntryStartY, 0, entryHeight }; | |||
| 33100 | bool capturedMouseOnEntry = false; | |||
| 33101 | for ( int i = 0; i < NUMPROFICIENCIES; ++i ) | |||
| 33102 | { | |||
| 33103 | Frame* allSkillEntries = allSkillEntriesRight; | |||
| 33104 | if ( i >= 8 ) | |||
| 33105 | { | |||
| 33106 | allSkillEntries = allSkillEntriesLeft; | |||
| 33107 | if ( i == 8 ) | |||
| 33108 | { | |||
| 33109 | entryResizePos.y = skillEntryStartY; | |||
| 33110 | } | |||
| 33111 | } | |||
| 33112 | auto entry = skillSheetEntryFrames[player.playernum].entryFrames[i]; | |||
| 33113 | ||||
| 33114 | if ( i >= skillSheetData.skillEntries.size() ) | |||
| 33115 | { | |||
| 33116 | entry->setDisabled(true); | |||
| 33117 | break; | |||
| 33118 | } | |||
| 33119 | entry->setDisabled(false); | |||
| 33120 | SDL_Rect entryPos = entry->getSize(); | |||
| 33121 | entryPos.y = entryResizePos.y; | |||
| 33122 | entryPos.h = entryResizePos.h; | |||
| 33123 | entry->setSize(entryPos); | |||
| 33124 | entryResizePos.y += entryResizePos.h; | |||
| 33125 | lowestSkillEntryY = std::max(lowestSkillEntryY, entryPos.y + entryPos.h); | |||
| 33126 | ||||
| 33127 | int proficiency = skillSheetData.skillEntries[i].skillId; | |||
| 33128 | bool updateSkillAssets = false; | |||
| 33129 | if ( !capturedMouseOnEntry ) | |||
| 33130 | { | |||
| 33131 | const bool entryCapturesMouse = entry->capturesMouse(); | |||
| 33132 | if ( entryCapturesMouse ) | |||
| 33133 | { | |||
| 33134 | capturedMouseOnEntry = true; | |||
| 33135 | mouseClickedOutOfBounds = false; | |||
| 33136 | if ( ::inputs.getVirtualMouse(player.playernum)->draw_cursor | |||
| 33137 | && entryCapturesMouse && !skillDescAreaCapturesMouse ) | |||
| 33138 | { | |||
| 33139 | highlightedSkill = i; | |||
| 33140 | if ( skillSlideDirection != 0 ) | |||
| 33141 | { | |||
| 33142 | if ( highlightedSkill >= 8 ) | |||
| 33143 | { | |||
| 33144 | skillSlideDirection = 1; | |||
| 33145 | } | |||
| 33146 | else | |||
| 33147 | { | |||
| 33148 | skillSlideDirection = -1; | |||
| 33149 | } | |||
| 33150 | } | |||
| 33151 | if ( Input::inputs[player.playernum].binaryToggle("MenuLeftClick") && inputs.bPlayerUsingKeyboardControl(player.playernum) ) | |||
| 33152 | { | |||
| 33153 | selectSkill(i); | |||
| 33154 | Input::inputs[player.playernum].consumeBinaryToggle("MenuLeftClick"); | |||
| 33155 | Player::soundActivate(); | |||
| 33156 | } | |||
| 33157 | } | |||
| 33158 | } | |||
| 33159 | } | |||
| 33160 | ||||
| 33161 | if ( !bSkillSheetEntryLoaded | |||
| 33162 | || skillsheetCache[player.playernum][proficiency].proficiencyLevelCached != stats[player.playernum]->getModifiedProficiency(proficiency) | |||
| 33163 | || skillsheetCache[player.playernum][proficiency].selectedSkill != selectedSkill | |||
| 33164 | || skillsheetCache[player.playernum][proficiency].highlightedSkill != highlightedSkill ) | |||
| 33165 | { | |||
| 33166 | if ( skillsheetCache[player.playernum][proficiency].proficiencyLevelCached != stats[player.playernum]->getModifiedProficiency(proficiency) | |||
| 33167 | || skillsheetCache[player.playernum][proficiency].selectedSkill != selectedSkill ) | |||
| 33168 | { | |||
| 33169 | reblitFrame = true; | |||
| 33170 | } | |||
| 33171 | skillsheetCache[player.playernum][proficiency].proficiencyLevelCached = stats[player.playernum]->getModifiedProficiency(proficiency); | |||
| 33172 | skillsheetCache[player.playernum][proficiency].selectedSkill = selectedSkill; | |||
| 33173 | skillsheetCache[player.playernum][proficiency].highlightedSkill = highlightedSkill; | |||
| 33174 | updateSkillAssets = true; | |||
| 33175 | } | |||
| 33176 | ||||
| 33177 | if ( updateSkillAssets ) | |||
| 33178 | { | |||
| 33179 | auto skillLevel = entry->findField("skill level"); | |||
| 33180 | char skillLevelText[32]; | |||
| 33181 | snprintf(skillLevelText, sizeof(skillLevelText), "%d", stats[player.playernum]->getModifiedProficiency(proficiency)); | |||
| 33182 | skillLevel->setText(skillLevelText); | |||
| 33183 | ||||
| 33184 | auto skillIconBg = entry->findImage("skill icon bg"); | |||
| 33185 | auto skillIconFg = entry->findImage("skill icon fg"); | |||
| 33186 | //skillIconFg->path = skillSheetData.skillEntries[i].skillIconPath; | |||
| 33187 | skillIconFg->disabled = true; | |||
| 33188 | auto statIcon = entry->findImage("stat icon"); | |||
| 33189 | statIcon->disabled = true; | |||
| 33190 | ||||
| 33191 | auto selectorIcon = entry->findImage("selector img"); | |||
| 33192 | selectorIcon->disabled = true; | |||
| 33193 | skillIconBg->disabled = false; | |||
| 33194 | ||||
| 33195 | if ( selectedSkill == i || highlightedSkill == i ) | |||
| 33196 | { | |||
| 33197 | selectorIcon->disabled = false; | |||
| 33198 | if ( selectedSkill == i && highlightedSkill == i ) | |||
| 33199 | { | |||
| 33200 | selectorIcon->path = (i < 8) ? "*#images/ui/SkillSheet/UI_Skills_SkillSelector100_01.png" : "*#images/ui/SkillSheet/UI_Skills_SkillSelector100R_01.png"; | |||
| 33201 | } | |||
| 33202 | else if ( highlightedSkill == i ) | |||
| 33203 | { | |||
| 33204 | selectorIcon->path = (i < 8) ? skillSheetData.highlightSkillImg : skillSheetData.highlightSkillImg_Right; | |||
| 33205 | } | |||
| 33206 | else if ( selectedSkill == i ) | |||
| 33207 | { | |||
| 33208 | selectorIcon->path = (i < 8) ? skillSheetData.selectSkillImg : skillSheetData.selectSkillImg_Right; | |||
| 33209 | } | |||
| 33210 | } | |||
| 33211 | ||||
| 33212 | if ( stats[player.playernum]->getModifiedProficiency(proficiency) >= SKILL_LEVEL_LEGENDARY ) | |||
| 33213 | { | |||
| 33214 | //skillIconFg->path = skillSheetData.skillEntries[i].skillIconPathLegend; | |||
| 33215 | skillLevel->setTextColor(skillSheetData.legendTextColor); | |||
| 33216 | if ( selectedSkill == i ) | |||
| 33217 | { | |||
| 33218 | skillIconBg->path = skillSheetData.iconBgSelectedPathLegend; | |||
| 33219 | } | |||
| 33220 | else | |||
| 33221 | { | |||
| 33222 | skillIconBg->path = skillSheetData.iconBgPathLegend; | |||
| 33223 | } | |||
| 33224 | } | |||
| 33225 | else if ( stats[player.playernum]->getModifiedProficiency(proficiency) >= SKILL_LEVEL_EXPERT ) | |||
| 33226 | { | |||
| 33227 | skillLevel->setTextColor(skillSheetData.expertTextColor); | |||
| 33228 | if ( selectedSkill == i ) | |||
| 33229 | { | |||
| 33230 | skillIconBg->path = skillSheetData.iconBgSelectedPathExpert; | |||
| 33231 | } | |||
| 33232 | else | |||
| 33233 | { | |||
| 33234 | skillIconBg->path = skillSheetData.iconBgPathExpert; | |||
| 33235 | } | |||
| 33236 | } | |||
| 33237 | else if ( stats[player.playernum]->getModifiedProficiency(proficiency) >= SKILL_LEVEL_BASIC ) | |||
| 33238 | { | |||
| 33239 | skillLevel->setTextColor(skillSheetData.noviceTextColor); | |||
| 33240 | if ( selectedSkill == i ) | |||
| 33241 | { | |||
| 33242 | skillIconBg->path = skillSheetData.iconBgSelectedPathNovice; | |||
| 33243 | } | |||
| 33244 | else | |||
| 33245 | { | |||
| 33246 | skillIconBg->path = skillSheetData.iconBgPathNovice; | |||
| 33247 | } | |||
| 33248 | } | |||
| 33249 | else | |||
| 33250 | { | |||
| 33251 | skillLevel->setTextColor(skillSheetData.defaultTextColor); | |||
| 33252 | if ( selectedSkill == i ) | |||
| 33253 | { | |||
| 33254 | skillIconBg->path = skillSheetData.iconBgSelectedPathDefault; | |||
| 33255 | } | |||
| 33256 | else | |||
| 33257 | { | |||
| 33258 | skillIconBg->path = skillSheetData.iconBgPathDefault; | |||
| 33259 | skillIconBg->disabled = true; | |||
| 33260 | } | |||
| 33261 | } | |||
| 33262 | } | |||
| 33263 | //statIcon->path = skillIconFg->path; | |||
| 33264 | //skillIconFg->path = ""; | |||
| 33265 | } | |||
| 33266 | ||||
| 33267 | //DebugTimers.addTimePoint("skill", "post basic numbers"); | |||
| 33268 | ||||
| 33269 | int lowestY = 0; | |||
| 33270 | ||||
| 33271 | SDL_Rect sliderPos = slider->getRailSize(); | |||
| 33272 | sliderPos.x = skillDescriptionFrame->getSize().w - 34; | |||
| 33273 | sliderPos.h = skillDescriptionFrame->getSize().h - 8; | |||
| 33274 | slider->setRailSize(sliderPos); | |||
| 33275 | ||||
| 33276 | int sliderOffsetW = 0; | |||
| 33277 | if ( slider->isDisabled() ) | |||
| 33278 | { | |||
| 33279 | int diff = (scrollOuterFramePos.w - (skillDescriptionFrame->getSize().w - 32)); | |||
| 33280 | sliderOffsetW = -diff; | |||
| 33281 | } | |||
| 33282 | else | |||
| 33283 | { | |||
| 33284 | int diff = (scrollOuterFramePos.w - (slider->getRailSize().x - 4 - 16)); | |||
| 33285 | sliderOffsetW = -diff; | |||
| 33286 | } | |||
| 33287 | if ( sliderOffsetW != 0 ) | |||
| 33288 | { | |||
| 33289 | bSkillSheetEntryLoaded = false; | |||
| 33290 | } | |||
| 33291 | ||||
| 33292 | scrollOuterFramePos.w += sliderOffsetW; | |||
| 33293 | scrollAreaOuterFrame->setSize(scrollOuterFramePos); | |||
| 33294 | scrollAreaPos.w = scrollOuterFramePos.w; | |||
| 33295 | scrollArea->setSize(scrollAreaPos); | |||
| 33296 | ||||
| 33297 | if ( slider->isDisabled() ) | |||
| 33298 | { | |||
| 33299 | scrollInertia = 0.0; | |||
| 33300 | } | |||
| 33301 | ||||
| 33302 | //DebugTimers.addTimePoint("skill", "post resize"); | |||
| 33303 | ||||
| 33304 | if ( selectedSkill >= 0 && selectedSkill < skillSheetData.skillEntries.size() ) | |||
| 33305 | { | |||
| 33306 | int proficiency = skillSheetData.skillEntries[selectedSkill].skillId; | |||
| 33307 | int proficiencyValue = stats[player.playernum]->getModifiedProficiency(proficiency); | |||
| 33308 | ||||
| 33309 | bool updateTitle = false; | |||
| 33310 | for ( auto& eff_t : skillSheetData.skillEntries[selectedSkill].effects ) | |||
| 33311 | { | |||
| 33312 | if ( eff_t.effectUpdatedAtSkillLevel != proficiencyValue | |||
| 33313 | || eff_t.effectUpdatedAtBaseSkillLevel != stats[player.playernum]->getProficiency(proficiency) ) | |||
| 33314 | { | |||
| 33315 | updateTitle = true; | |||
| 33316 | break; | |||
| 33317 | } | |||
| 33318 | } | |||
| 33319 | ||||
| 33320 | if ( !bSkillSheetEntryLoaded || updateTitle ) | |||
| 33321 | { | |||
| 33322 | auto skillLvlHeaderVal = scrollArea->findField("skill lvl header val"); | |||
| 33323 | char skillLvl[128] = ""; | |||
| 33324 | std::string skillLvlTitle = ""; | |||
| 33325 | if ( proficiencyValue >= SKILL_LEVEL_LEGENDARY ) | |||
| 33326 | { | |||
| 33327 | skillLvlTitle = Language::get(369); | |||
| 33328 | } | |||
| 33329 | else if ( proficiencyValue >= SKILL_LEVEL_MASTER ) | |||
| 33330 | { | |||
| 33331 | skillLvlTitle = Language::get(368); | |||
| 33332 | } | |||
| 33333 | else if ( proficiencyValue >= SKILL_LEVEL_EXPERT ) | |||
| 33334 | { | |||
| 33335 | skillLvlTitle = Language::get(367); | |||
| 33336 | } | |||
| 33337 | else if ( proficiencyValue >= SKILL_LEVEL_SKILLED ) | |||
| 33338 | { | |||
| 33339 | skillLvlTitle = Language::get(366); | |||
| 33340 | } | |||
| 33341 | else if ( proficiencyValue >= SKILL_LEVEL_BASIC ) | |||
| 33342 | { | |||
| 33343 | skillLvlTitle = Language::get(365); | |||
| 33344 | } | |||
| 33345 | else if ( proficiencyValue >= SKILL_LEVEL_NOVICE ) | |||
| 33346 | { | |||
| 33347 | skillLvlTitle = Language::get(364); | |||
| 33348 | } | |||
| 33349 | else | |||
| 33350 | { | |||
| 33351 | skillLvlTitle = Language::get(363); | |||
| 33352 | } | |||
| 33353 | skillLvlTitle.erase(std::remove(skillLvlTitle.begin(), skillLvlTitle.end(), ' '), skillLvlTitle.end()); // trim whitespace | |||
| 33354 | int effectsModifier = stats[player.playernum]->getModifiedProficiency(proficiency) - stats[player.playernum]->getProficiency(proficiency); | |||
| 33355 | if ( proficiencyValue > 100 ) | |||
| 33356 | { | |||
| 33357 | effectsModifier = std::max(effectsModifier - (proficiencyValue - 100), 0); | |||
| 33358 | } | |||
| 33359 | if ( effectsModifier > 0 ) | |||
| 33360 | { | |||
| 33361 | snprintf(skillLvl, sizeof(skillLvl), "%s (%d + %d)", skillLvlTitle.c_str(), | |||
| 33362 | stats[player.playernum]->getProficiency(proficiency), effectsModifier); | |||
| 33363 | } | |||
| 33364 | else if ( effectsModifier < 0 ) | |||
| 33365 | { | |||
| 33366 | snprintf(skillLvl, sizeof(skillLvl), "%s (%d - %d)", skillLvlTitle.c_str(), | |||
| 33367 | stats[player.playernum]->getProficiency(proficiency), abs(effectsModifier)); | |||
| 33368 | } | |||
| 33369 | else | |||
| 33370 | { | |||
| 33371 | snprintf(skillLvl, sizeof(skillLvl), "%s (%d)", skillLvlTitle.c_str(), stats[player.playernum]->getModifiedProficiency(proficiency)); | |||
| 33372 | } | |||
| 33373 | skillLvlHeaderVal->setText(skillLvl); | |||
| 33374 | ||||
| 33375 | SDL_Rect skillLvlHeaderValPos = skillLvlHeaderVal->getSize(); | |||
| 33376 | skillLvlHeaderValPos.x += sliderOffsetW; | |||
| 33377 | skillLvlHeaderVal->setSize(skillLvlHeaderValPos); | |||
| 33378 | ||||
| 33379 | if ( !bSkillSheetEntryLoaded ) | |||
| 33380 | { | |||
| 33381 | auto skillTitleTxt = innerFrame->findField("skill title txt"); | |||
| 33382 | skillTitleTxt->setText(skillSheetData.skillEntries[selectedSkill].name.c_str()); | |||
| 33383 | ||||
| 33384 | auto statTypeTxt = scrollArea->findField("stat type txt"); | |||
| 33385 | auto statIcon = scrollArea->findImage("stat icon"); | |||
| 33386 | statIcon->path = skillSheetData.skillEntries[selectedSkill].statIconPath; | |||
| 33387 | switch ( getStatForProficiency(proficiency) ) | |||
| 33388 | { | |||
| 33389 | case STAT_STR: | |||
| 33390 | statTypeTxt->setText(Language::get(5300)); | |||
| 33391 | break; | |||
| 33392 | case STAT_DEX: | |||
| 33393 | statTypeTxt->setText(Language::get(5301)); | |||
| 33394 | break; | |||
| 33395 | case STAT_CON: | |||
| 33396 | statTypeTxt->setText(Language::get(5302)); | |||
| 33397 | break; | |||
| 33398 | case STAT_INT: | |||
| 33399 | statTypeTxt->setText(Language::get(5303)); | |||
| 33400 | break; | |||
| 33401 | case STAT_PER: | |||
| 33402 | statTypeTxt->setText(Language::get(5304)); | |||
| 33403 | break; | |||
| 33404 | case STAT_CHR: | |||
| 33405 | statTypeTxt->setText(Language::get(5305)); | |||
| 33406 | break; | |||
| 33407 | default: | |||
| 33408 | break; | |||
| 33409 | } | |||
| 33410 | ||||
| 33411 | SDL_Rect statTypeTxtPos = statTypeTxt->getSize(); | |||
| 33412 | statTypeTxtPos.x += sliderOffsetW; | |||
| 33413 | statTypeTxt->setSize(statTypeTxtPos); | |||
| 33414 | statIcon->pos.x += sliderOffsetW; | |||
| 33415 | } | |||
| 33416 | } | |||
| 33417 | ||||
| 33418 | //DebugTimers.addTimePoint("skill", "process 1"); | |||
| 33419 | ||||
| 33420 | int moveEffectsOffsetY = 0; | |||
| 33421 | const int actualFontHeight = 20; | |||
| 33422 | if ( !bSkillSheetEntryLoaded ) | |||
| 33423 | { | |||
| 33424 | auto skillDescriptionTxt = scrollArea->findField("skill desc txt"); | |||
| 33425 | auto skillDescriptionBgFrame = scrollArea->findFrame("skill desc bg frame"); | |||
| 33426 | //Font* actualFont = Font::get(skillDescriptionTxt->getFont()); | |||
| 33427 | SDL_Rect skillDescriptionTxtPos = skillDescriptionTxt->getSize(); | |||
| 33428 | skillDescriptionTxtPos.w = scrollAreaPos.w; | |||
| 33429 | skillDescriptionTxt->setSize(skillDescriptionTxtPos); | |||
| 33430 | ||||
| 33431 | int txtHeightOld = skillDescriptionTxt->getNumTextLines() * actualFontHeight/*actualFont->height(true)*/; | |||
| 33432 | skillDescriptionTxt->setText(skillSheetData.skillEntries[selectedSkill].description.c_str()); | |||
| 33433 | skillDescriptionTxt->reflowTextToFit(0); | |||
| 33434 | int txtHeightNew = skillDescriptionTxt->getNumTextLines() * actualFontHeight/*actualFont->height(true)*/; | |||
| 33435 | ||||
| 33436 | if ( txtHeightNew != txtHeightOld ) | |||
| 33437 | { | |||
| 33438 | moveEffectsOffsetY = (txtHeightNew - txtHeightOld); | |||
| 33439 | } | |||
| 33440 | skillDescriptionBgFrame->setSize(SDL_Rect{skillDescriptionTxtPos.x, skillDescriptionTxtPos.y - 4, | |||
| 33441 | skillDescriptionTxtPos.w, txtHeightNew + 8 }); | |||
| 33442 | lowestY = std::max(lowestY, skillDescriptionTxt->getSize().y + skillDescriptionTxt->getNumTextLines() * actualFontHeight/*actualFont->height(true)*/); | |||
| 33443 | ||||
| 33444 | std::string staticImgPath = "*#images/ui/SkillSheet/UI_Skills_Desc_Full_"; | |||
| 33445 | staticImgPath += std::to_string(skillDescriptionBgFrame->getSize().w) + 'x' + std::to_string(skillDescriptionBgFrame->getSize().h) + ".png"; | |||
| 33446 | ||||
| 33447 | auto staticImg = Image::get(staticImgPath.c_str()); | |||
| 33448 | if ( staticImg && staticImg->getWidth() > 0 && *cvar_skillsheet_optimise ) | |||
| 33449 | { | |||
| 33450 | for ( auto img : skillDescriptionBgFrame->getImages() ) | |||
| 33451 | { | |||
| 33452 | img->disabled = true; | |||
| 33453 | } | |||
| 33454 | auto mm = skillDescriptionBgFrame->findImage(skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 33455 | mm->disabled = false; | |||
| 33456 | mm->path = staticImgPath; | |||
| 33457 | mm->pos = SDL_Rect{ 0, 0, skillDescriptionBgFrame->getSize().w, skillDescriptionBgFrame->getSize().h }; | |||
| 33458 | } | |||
| 33459 | else | |||
| 33460 | { | |||
| 33461 | for ( auto img : skillDescriptionBgFrame->getImages() ) | |||
| 33462 | { | |||
| 33463 | img->disabled = false; | |||
| 33464 | } | |||
| 33465 | auto mm = skillDescriptionBgFrame->findImage(skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 33466 | mm->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox_M_00.png"; | |||
| 33467 | imageResizeToContainer9x9(skillDescriptionBgFrame, | |||
| 33468 | SDL_Rect{ 0, 0, skillDescriptionBgFrame->getSize().w, skillDescriptionBgFrame->getSize().h }, skillsheetEffectBackgroundImages); | |||
| 33469 | } | |||
| 33470 | } | |||
| 33471 | ||||
| 33472 | bool skillLVLUpdated = false; | |||
| 33473 | int previousEffectFrameHeight = 0; | |||
| 33474 | ||||
| 33475 | auto effectFrameBgImgTmp = scrollArea->findImage("effect frame bg tmp"); | |||
| 33476 | effectFrameBgImgTmp->disabled = false; | |||
| 33477 | ||||
| 33478 | for ( int eff = 0; eff < 10; ++eff ) | |||
| 33479 | { | |||
| 33480 | auto effectFrame = skillSheetEntryFrames[player.playernum].effectFrames[eff]; | |||
| 33481 | if ( !effectFrame ) { continue; } | |||
| 33482 | ||||
| 33483 | effectFrame->setDisabled(true); | |||
| 33484 | ||||
| 33485 | if ( eff < skillSheetData.skillEntries[selectedSkill].effects.size() ) | |||
| 33486 | { | |||
| 33487 | SDL_Rect effectFramePos = effectFrame->getSize(); | |||
| 33488 | effectFramePos.w = scrollAreaPos.w; | |||
| 33489 | effectFrameBgImgTmp->pos.w = effectFramePos.w; | |||
| 33490 | ||||
| 33491 | if ( moveEffectsOffsetY != 0 ) | |||
| 33492 | { | |||
| 33493 | effectFramePos.y += moveEffectsOffsetY; | |||
| 33494 | } | |||
| 33495 | effectFrame->setSize(effectFramePos); | |||
| 33496 | ||||
| 33497 | effectFrame->setDisabled(false); | |||
| 33498 | ||||
| 33499 | auto& effect_t = skillSheetData.skillEntries[selectedSkill].effects[eff]; | |||
| 33500 | ||||
| 33501 | bool bEffUpdated = false; | |||
| 33502 | if ( (effect_t.bAllowRealtimeUpdate && (ticks % (std::max(TICKS_PER_SECOND50, MAXPLAYERS4 * 10))) == (player.playernum * 10)) | |||
| 33503 | || effect_t.effectUpdatedAtSkillLevel != stats[player.playernum]->getModifiedProficiency(proficiency) | |||
| 33504 | || effect_t.effectUpdatedAtBaseSkillLevel != stats[player.playernum]->getProficiency(proficiency) | |||
| 33505 | || effect_t.effectUpdatedAtMonsterType != stats[player.playernum]->type | |||
| 33506 | || effect_t.value == "" ) | |||
| 33507 | { | |||
| 33508 | if ( effect_t.effectUpdatedAtSkillLevel != stats[player.playernum]->getModifiedProficiency(proficiency) | |||
| 33509 | || effect_t.effectUpdatedAtBaseSkillLevel != stats[player.playernum]->getProficiency(proficiency) ) | |||
| 33510 | { | |||
| 33511 | skillLVLUpdated = true; | |||
| 33512 | bEffUpdated = true; | |||
| 33513 | } | |||
| 33514 | else if ( effect_t.effectUpdatedAtMonsterType != stats[player.playernum]->type ) | |||
| 33515 | { | |||
| 33516 | bEffUpdated = true; | |||
| 33517 | } | |||
| 33518 | effect_t.effectUpdatedAtSkillLevel = stats[player.playernum]->getModifiedProficiency(proficiency); | |||
| 33519 | effect_t.effectUpdatedAtBaseSkillLevel = stats[player.playernum]->getProficiency(proficiency); | |||
| 33520 | effect_t.effectUpdatedAtMonsterType = stats[player.playernum]->type; | |||
| 33521 | std::string oldValue = effect_t.value; | |||
| 33522 | effect_t.value = formatSkillSheetEffects(player.playernum, proficiency, effect_t.tag, effect_t.rawValue); | |||
| 33523 | if ( oldValue != effect_t.value ) | |||
| 33524 | { | |||
| 33525 | bEffUpdated = true; | |||
| 33526 | } | |||
| 33527 | auto effectValFrame = effectFrame->findFrame("effect val frame"); | |||
| 33528 | auto effectVal = effectValFrame->findField("effect val"); | |||
| 33529 | effectVal->setText(effect_t.value.c_str()); | |||
| 33530 | if ( effect_t.bAllowAutoResizeValue ) | |||
| 33531 | { | |||
| 33532 | auto textGetValue = Text::get(effectVal->getLongestLine().c_str(), effectVal->getFont(), | |||
| 33533 | effectVal->getTextColor(), effectVal->getOutlineColor()); | |||
| 33534 | effect_t.cachedWidth = textGetValue->getWidth(); | |||
| 33535 | } | |||
| 33536 | } | |||
| 33537 | ||||
| 33538 | if ( !bSkillSheetEntryLoaded || bEffUpdated ) | |||
| 33539 | { | |||
| 33540 | reblitFrame = true; | |||
| 33541 | ||||
| 33542 | auto effectValFrame = effectFrame->findFrame("effect val frame"); | |||
| 33543 | auto effectVal = effectValFrame->findField("effect val"); | |||
| 33544 | auto effectTxtFrame = effectFrame->findFrame("effect txt frame"); | |||
| 33545 | auto effectTxt = effectTxtFrame->findField("effect txt"); | |||
| 33546 | auto effectBgImgFrame = effectFrame->findFrame("effect val bg frame"); | |||
| 33547 | effectTxt->setText(effect_t.title.c_str()); | |||
| 33548 | ||||
| 33549 | { | |||
| 33550 | // adjust position to match width of container | |||
| 33551 | SDL_Rect effectTxtFramePos = effectTxtFrame->getSize(); | |||
| 33552 | SDL_Rect effectValFramePos = effectValFrame->getSize(); | |||
| 33553 | SDL_Rect effectBgImgFramePos = effectBgImgFrame->getSize(); | |||
| 33554 | const auto& effectStartOffsetX = skillSheetData.skillEntries[selectedSkill].effectStartOffsetX; | |||
| 33555 | const auto& effectBackgroundOffsetX = skillSheetData.skillEntries[selectedSkill].effectBackgroundOffsetX; | |||
| 33556 | const auto& effectBackgroundWidth = skillSheetData.skillEntries[selectedSkill].effectBackgroundWidth; | |||
| 33557 | int valueCustomWidthOffset = effect_t.valueCustomWidthOffset; | |||
| 33558 | effectBgImgFramePos.x = effectFrame->getSize().w - effectStartOffsetX - effectBackgroundOffsetX - valueCustomWidthOffset; | |||
| 33559 | effectBgImgFramePos.w = effectBackgroundWidth + valueCustomWidthOffset; | |||
| 33560 | effectTxtFramePos.w = effectFrame->getSize().w - effectStartOffsetX - effectBackgroundOffsetX - valueCustomWidthOffset; | |||
| 33561 | effectValFramePos.x = effectFrame->getSize().w - effectStartOffsetX - valueCustomWidthOffset; | |||
| 33562 | effectValFramePos.w = effectStartOffsetX + valueCustomWidthOffset; | |||
| 33563 | if ( effect_t.bAllowAutoResizeValue | |||
| 33564 | && effect_t.cachedWidth > (effectValFramePos.w - effectVal->getSize().x - effectBackgroundOffsetX) ) | |||
| 33565 | { | |||
| 33566 | int diff = (effect_t.cachedWidth - (effectValFramePos.w - effectVal->getSize().x - effectBackgroundOffsetX)); | |||
| 33567 | effectBgImgFramePos.x -= diff; | |||
| 33568 | effectBgImgFramePos.w += diff; | |||
| 33569 | effectTxtFramePos.w -= diff; | |||
| 33570 | effectValFramePos.x -= diff; | |||
| 33571 | effectValFramePos.w += diff; | |||
| 33572 | } | |||
| 33573 | ||||
| 33574 | effectTxtFrame->setSize(effectTxtFramePos); | |||
| 33575 | effectValFrame->setSize(effectValFramePos); | |||
| 33576 | effectBgImgFrame->setSize(effectBgImgFramePos); | |||
| 33577 | } | |||
| 33578 | ||||
| 33579 | effectFramePos = effectFrame->getSize(); | |||
| 33580 | ||||
| 33581 | //Font* effectTxtFont = Font::get(effectTxt->getFont()); | |||
| 33582 | const int fontHeight = 20; | |||
| 33583 | //effectTxtFont->sizeText("_", nullptr, &fontHeight); | |||
| 33584 | int numEffectLines = effectTxt->getNumTextLines(); | |||
| 33585 | int numEffectValLines = effectVal->getNumTextLines(); | |||
| 33586 | int numEffectValBgLines = numEffectValLines; | |||
| 33587 | if ( numEffectLines > 1 || numEffectValLines > 1 ) | |||
| 33588 | { | |||
| 33589 | if ( numEffectValLines <= 1 ) | |||
| 33590 | { | |||
| 33591 | // single line value, only need lines of title | |||
| 33592 | effectFramePos.h = (fontHeight * std::max(1, numEffectLines)) + 8; | |||
| 33593 | } | |||
| 33594 | else | |||
| 33595 | { | |||
| 33596 | if ( numEffectLines <= numEffectValLines ) | |||
| 33597 | { | |||
| 33598 | numEffectValLines += 1; // need more buffer area for the values as it is larger than title | |||
| 33599 | effectFramePos.h = (fontHeight * numEffectValLines) + 8; | |||
| 33600 | } | |||
| 33601 | else | |||
| 33602 | { | |||
| 33603 | effectFramePos.h = (fontHeight * numEffectLines) + 8; | |||
| 33604 | } | |||
| 33605 | } | |||
| 33606 | } | |||
| 33607 | else | |||
| 33608 | { | |||
| 33609 | // both title and value are 1 line, add .5 padding | |||
| 33610 | effectFramePos.h = (fontHeight) * 1.5 + 8; | |||
| 33611 | } | |||
| 33612 | if ( eff > 0 ) | |||
| 33613 | { | |||
| 33614 | effectFramePos.y = previousEffectFrameHeight; // don't adjust first effect frame y pos | |||
| 33615 | } | |||
| 33616 | else | |||
| 33617 | { | |||
| 33618 | effectFrameBgImgTmp->pos.y = effectFramePos.y; | |||
| 33619 | } | |||
| 33620 | effectFrame->setSize(effectFramePos); | |||
| 33621 | ||||
| 33622 | { | |||
| 33623 | // adjust position to match height of container | |||
| 33624 | SDL_Rect effectTxtFramePos = effectTxtFrame->getSize(); | |||
| 33625 | SDL_Rect effectValFramePos = effectValFrame->getSize(); | |||
| 33626 | SDL_Rect effectBgImgFramePos = effectBgImgFrame->getSize(); | |||
| 33627 | const int containerHeight = effectFramePos.h - 4; | |||
| 33628 | effectTxtFramePos.h = containerHeight; | |||
| 33629 | effectValFramePos.h = containerHeight; | |||
| 33630 | effectTxtFrame->setSize(effectTxtFramePos); | |||
| 33631 | effectValFrame->setSize(effectValFramePos); | |||
| 33632 | ||||
| 33633 | SDL_Rect effectTxtPos = effectTxt->getSize(); | |||
| 33634 | effectTxtPos.h = containerHeight; | |||
| 33635 | effectTxt->setSize(effectTxtPos); | |||
| 33636 | SDL_Rect effectValPos = effectVal->getSize(); | |||
| 33637 | effectValPos.h = containerHeight; | |||
| 33638 | effectVal->setSize(effectValPos); | |||
| 33639 | ||||
| 33640 | effectBgImgFramePos.h = (fontHeight * numEffectValBgLines) + 8; | |||
| 33641 | effectBgImgFramePos.y = (containerHeight / 2 - effectBgImgFramePos.h / 2); | |||
| 33642 | effectBgImgFrame->setSize(effectBgImgFramePos); | |||
| 33643 | ||||
| 33644 | auto effectFrameBgImg = effectFrame->findImage("effect frame bg highlight"); | |||
| 33645 | effectFrameBgImg->pos = SDL_Rect{ 0, effectFrame->getSize().h - 2, effectFrame->getSize().w, 1 }; | |||
| 33646 | } | |||
| 33647 | ||||
| 33648 | { | |||
| 33649 | // adjust inner background image elements | |||
| 33650 | ||||
| 33651 | std::string staticImgPath = "*#images/ui/SkillSheet/UI_Skills_Eff_Full_"; | |||
| 33652 | staticImgPath += std::to_string(effectBgImgFrame->getSize().w) + 'x' + std::to_string(effectBgImgFrame->getSize().h) + ".png"; | |||
| 33653 | ||||
| 33654 | auto staticImg = Image::get(staticImgPath.c_str()); | |||
| 33655 | if ( staticImg && staticImg->getWidth() > 0 && *cvar_skillsheet_optimise ) | |||
| 33656 | { | |||
| 33657 | for ( auto img : effectBgImgFrame->getImages() ) | |||
| 33658 | { | |||
| 33659 | img->disabled = true; | |||
| 33660 | } | |||
| 33661 | auto mm = effectBgImgFrame->findImage(skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 33662 | mm->disabled = false; | |||
| 33663 | mm->path = staticImgPath; | |||
| 33664 | mm->color = makeColorRGB(255, 255, 255); | |||
| 33665 | mm->pos = SDL_Rect{ 0, 0, effectBgImgFrame->getSize().w, effectBgImgFrame->getSize().h }; | |||
| 33666 | } | |||
| 33667 | else | |||
| 33668 | { | |||
| 33669 | for ( auto img : effectBgImgFrame->getImages() ) | |||
| 33670 | { | |||
| 33671 | img->disabled = false; | |||
| 33672 | } | |||
| 33673 | auto mm = effectBgImgFrame->findImage(skillsheetEffectBackgroundImages[MIDDLE].c_str()); | |||
| 33674 | mm->path = "*#images/ui/SkillSheet/UI_Skills_EffectBG_M00.png"; | |||
| 33675 | mm->color = makeColor(51, 33, 26, 255); | |||
| 33676 | imageResizeToContainer9x9(effectBgImgFrame, | |||
| 33677 | SDL_Rect{ 0, 0, effectBgImgFrame->getSize().w, effectBgImgFrame->getSize().h }, skillsheetEffectBackgroundImages); | |||
| 33678 | /*static std::map<int, std::pair<int, int>> sizes; | |||
| 33679 | sizes[effectBgImgFrame->getSize().w + effectBgImgFrame->getSize().h * 1000] = std::make_pair(effectBgImgFrame->getSize().w, effectBgImgFrame->getSize().h); | |||
| 33680 | printlog("sizes"); | |||
| 33681 | for ( auto & pair : sizes ) | |||
| 33682 | { | |||
| 33683 | printlog("%d | %d", pair.second.first, pair.second.second); | |||
| 33684 | }*/ | |||
| 33685 | } | |||
| 33686 | ||||
| 33687 | ||||
| 33688 | } | |||
| 33689 | } | |||
| 33690 | ||||
| 33691 | lowestY = std::max(lowestY, effectFrame->getSize().y + effectFrame->getSize().h); | |||
| 33692 | effectFrameBgImgTmp->pos.h = lowestY - effectFrameBgImgTmp->pos.y; | |||
| 33693 | // check marquee if needed | |||
| 33694 | //if ( false ) | |||
| 33695 | //{ | |||
| 33696 | // auto textGetTitle = Text::get(effectTxt->getText(), effectTxt->getFont(), | |||
| 33697 | // effectTxt->getTextColor(), effectTxt->getOutlineColor()); | |||
| 33698 | // int titleWidth = textGetTitle->getWidth(); | |||
| 33699 | // if ( numEffectLines > 1 ) | |||
| 33700 | // { | |||
| 33701 | // auto textGetTitle = Text::get(effectTxt->getLongestLine().c_str(), effectTxt->getFont(), | |||
| 33702 | // effectTxt->getTextColor(), effectTxt->getOutlineColor()); | |||
| 33703 | // titleWidth = textGetTitle->getWidth(); | |||
| 33704 | // } | |||
| 33705 | ||||
| 33706 | // if ( ticks - openTick > TICKS_PER_SECOND * 2 ) | |||
| 33707 | // { | |||
| 33708 | // bool doMarquee = false; | |||
| 33709 | // doMarquee = doMarquee || (titleWidth > (effectTxt->getSize().x + effectTxtFrame->getSize().w)); | |||
| 33710 | // doMarquee = doMarquee || (valueWidth > (effectVal->getSize().x + effectValFrame->getSize().w)); | |||
| 33711 | ||||
| 33712 | // if ( doMarquee ) | |||
| 33713 | // { | |||
| 33714 | // const real_t fpsScale = getFPSScale(60.0); // ported from 60Hz | |||
| 33715 | // effect_t.marquee[player.playernum] += (.005 * fpsScale); | |||
| 33716 | // //effect_t.marquee[player.playernum] = std::min(1.0, effect_t.marquee[player.playernum]); | |||
| 33717 | ||||
| 33718 | // /*if ( effect_t.marqueeTicks[player.playernum] == 0 && effect_t.marquee[player.playernum] >= 1.0 ) | |||
| 33719 | // { | |||
| 33720 | // effect_t.marqueeTicks[player.playernum] = ticks; | |||
| 33721 | // }*/ | |||
| 33722 | // /*if ( effect_t.marqueeTicks[player.playernum] > 0 && (ticks - effect_t.marqueeTicks[player.playernum] > TICKS_PER_SECOND * 2) ) | |||
| 33723 | // { | |||
| 33724 | // effect_t.marqueeTicks[player.playernum] = 0; | |||
| 33725 | // effect_t.marquee[player.playernum] = 0.0; | |||
| 33726 | // }*/ | |||
| 33727 | // } | |||
| 33728 | // } | |||
| 33729 | // SDL_Rect posTitle = effectTxt->getSize(); | |||
| 33730 | // int scrollTitleLength = titleWidth - effectTxtFrame->getSize().w; | |||
| 33731 | // if ( titleWidth <= effectTxtFrame->getSize().w ) | |||
| 33732 | // { | |||
| 33733 | // scrollTitleLength = 0; | |||
| 33734 | // posTitle.x = 0; | |||
| 33735 | // effect_t.marqueeCompleted[player.playernum] = false; | |||
| 33736 | // effect_t.marquee[player.playernum] = 0.0; | |||
| 33737 | // effect_t.marqueeTicks[player.playernum] = 0; | |||
| 33738 | // } | |||
| 33739 | // else | |||
| 33740 | // { | |||
| 33741 | // posTitle.x = std::max((int)(-effect_t.marquee[player.playernum] * 100), -scrollTitleLength); | |||
| 33742 | // if ( posTitle.x == -scrollTitleLength ) | |||
| 33743 | // { | |||
| 33744 | // if ( !effect_t.marqueeCompleted[player.playernum] ) | |||
| 33745 | // { | |||
| 33746 | // effect_t.marqueeTicks[player.playernum] = ticks; | |||
| 33747 | // } | |||
| 33748 | // effect_t.marqueeCompleted[player.playernum] = true; | |||
| 33749 | // } | |||
| 33750 | // else | |||
| 33751 | // { | |||
| 33752 | // effect_t.marqueeCompleted[player.playernum] = false; | |||
| 33753 | // } | |||
| 33754 | // } | |||
| 33755 | // //posTitle.x = -scrollTitleLength * effect_t.marquee[player.playernum]; | |||
| 33756 | // effectTxt->setSize(posTitle); | |||
| 33757 | ||||
| 33758 | // SDL_Rect posValue = effectVal->getSize(); | |||
| 33759 | // int scrollValueLength = valueWidth - effectValFrame->getSize().w; | |||
| 33760 | // if ( valueWidth <= effectValFrame->getSize().w ) | |||
| 33761 | // { | |||
| 33762 | // scrollValueLength = 0; | |||
| 33763 | // } | |||
| 33764 | // posValue.x = -scrollValueLength * effect_t.marquee[player.playernum]; | |||
| 33765 | // effectVal->setSize(posValue); | |||
| 33766 | //} | |||
| 33767 | previousEffectFrameHeight = effectFrame->getSize().y + effectFrame->getSize().h; | |||
| 33768 | //DebugTimers.addTimePoint("skill", effectFrame->getName()); | |||
| 33769 | } | |||
| 33770 | } | |||
| 33771 | ||||
| 33772 | //DebugTimers.addTimePoint("skill", "process fx 2"); | |||
| 33773 | ||||
| 33774 | if ( false ) | |||
| 33775 | { | |||
| 33776 | Uint32 lastMarqueeTick = 0; | |||
| 33777 | bool allMarqueeCompleted = true; | |||
| 33778 | for ( auto& effect_t : skillSheetData.skillEntries[selectedSkill].effects ) | |||
| 33779 | { | |||
| 33780 | if ( effect_t.marquee[player.playernum] > 0.0 ) | |||
| 33781 | { | |||
| 33782 | if ( !effect_t.marqueeCompleted[player.playernum] ) | |||
| 33783 | { | |||
| 33784 | allMarqueeCompleted = false; | |||
| 33785 | } | |||
| 33786 | lastMarqueeTick = std::max(effect_t.marqueeTicks[player.playernum], lastMarqueeTick); | |||
| 33787 | } | |||
| 33788 | } | |||
| 33789 | if ( allMarqueeCompleted && lastMarqueeTick > 0 && ((ticks - lastMarqueeTick) > 2 * TICKS_PER_SECOND50) ) | |||
| 33790 | { | |||
| 33791 | for ( auto& effect_t : skillSheetData.skillEntries[selectedSkill].effects ) | |||
| 33792 | { | |||
| 33793 | effect_t.marquee[player.playernum] = 0.0; | |||
| 33794 | effect_t.marqueeCompleted[player.playernum] = false; | |||
| 33795 | effect_t.marqueeTicks[player.playernum] = 0; | |||
| 33796 | } | |||
| 33797 | openTick = (ticks > TICKS_PER_SECOND50) ? (ticks - TICKS_PER_SECOND50) : ticks; | |||
| 33798 | } | |||
| 33799 | } | |||
| 33800 | ||||
| 33801 | // legend panel | |||
| 33802 | auto legendDivImg = scrollArea->findImage("legend div"); | |||
| 33803 | legendDivImg->pos.x = scrollArea->getSize().w / 2 - legendDivImg->pos.w / 2; | |||
| 33804 | legendDivImg->pos.y = lowestY + 8; | |||
| 33805 | auto legendDivTxt = scrollArea->findField("legend div text"); | |||
| 33806 | SDL_Rect legendDivTxtPos = legendDivTxt->getSize(); | |||
| 33807 | legendDivTxtPos.x = legendDivImg->pos.x; | |||
| 33808 | legendDivTxtPos.w = legendDivImg->pos.w; | |||
| 33809 | legendDivTxtPos.y = legendDivImg->pos.y + legendDivImg->pos.h - 16; | |||
| 33810 | legendDivTxtPos.h = actualFontHeight/*actualFont->height(true)*/; | |||
| 33811 | legendDivTxt->setSize(legendDivTxtPos); | |||
| 33812 | lowestY = legendDivTxtPos.y + legendDivTxtPos.h; | |||
| 33813 | ||||
| 33814 | auto legendBackerImg = scrollArea->findImage("legend txt backer img"); | |||
| 33815 | legendBackerImg->disabled = true; | |||
| 33816 | if ( proficiencyValue >= SKILL_LEVEL_LEGENDARY ) | |||
| 33817 | { | |||
| 33818 | legendBackerImg->pos.x = scrollArea->getSize().w / 2 - legendBackerImg->pos.w / 2; | |||
| 33819 | legendBackerImg->pos.y = legendDivTxtPos.y + 6; | |||
| 33820 | legendBackerImg->disabled = false; | |||
| 33821 | } | |||
| 33822 | ||||
| 33823 | auto legendFrame = skillSheetEntryFrames[player.playernum].legendFrame; | |||
| 33824 | SDL_Rect legendPos = legendFrame->getSize(); | |||
| 33825 | legendPos.y = lowestY; | |||
| 33826 | legendPos.w = scrollArea->getSize().w; | |||
| 33827 | legendFrame->setSize(legendPos); | |||
| 33828 | ||||
| 33829 | auto tl = legendFrame->findImage("top left img"); | |||
| 33830 | auto tm = legendFrame->findImage("top img"); | |||
| 33831 | auto tr = legendFrame->findImage("top right img"); | |||
| 33832 | tm->pos.w = legendPos.w - tl->pos.w - tr->pos.w; | |||
| 33833 | tr->pos.x = legendPos.w - tr->pos.w; | |||
| 33834 | ||||
| 33835 | if ( !bSkillSheetEntryLoaded || skillLVLUpdated ) | |||
| 33836 | { | |||
| 33837 | reblitFrame = true; | |||
| 33838 | Uint32 legendGoldColor = makeColor(230, 183, 20, 255); | |||
| 33839 | Uint32 legendRegularColor = makeColor(201, 162, 100, 255); | |||
| 33840 | ||||
| 33841 | auto legendText = legendFrame->findField("legend text"); | |||
| 33842 | SDL_Rect legendTextPos = legendText->getSize(); | |||
| 33843 | legendText->setText(skillSheetData.skillEntries[selectedSkill].legendaryDescription.c_str()); | |||
| 33844 | legendTextPos.w = tm->pos.w; | |||
| 33845 | legendText->setSize(legendTextPos); | |||
| 33846 | legendText->reflowTextToFit(0); | |||
| 33847 | legendTextPos.h = legendText->getNumTextLines() * actualFontHeight; | |||
| 33848 | legendTextPos.y = tm->pos.y + tm->pos.h / 2 /*+ 2*/; | |||
| 33849 | legendTextPos.h += 4; // handle hanging chars | |||
| 33850 | legendText->setSize(legendTextPos); | |||
| 33851 | ||||
| 33852 | auto ml = legendFrame->findImage("middle left img"); | |||
| 33853 | ml->pos.h = legendTextPos.h - tm->pos.h; | |||
| 33854 | auto mm = legendFrame->findImage("middle img"); | |||
| 33855 | mm->pos.h = ml->pos.h; | |||
| 33856 | auto mr = legendFrame->findImage("middle right img"); | |||
| 33857 | mr->pos.h = ml->pos.h; | |||
| 33858 | mm->pos.w = legendPos.w - ml->pos.w - mr->pos.w; | |||
| 33859 | mr->pos.x = legendPos.w - mr->pos.w; | |||
| 33860 | ||||
| 33861 | auto bl = legendFrame->findImage("bottom left img"); | |||
| 33862 | bl->pos.y = ml->pos.y + ml->pos.h; | |||
| 33863 | auto bm = legendFrame->findImage("bottom img"); | |||
| 33864 | bm->pos.y = bl->pos.y; | |||
| 33865 | auto br = legendFrame->findImage("bottom right img"); | |||
| 33866 | br->pos.y = bl->pos.y; | |||
| 33867 | bm->pos.w = legendPos.w - bl->pos.w - br->pos.w; | |||
| 33868 | br->pos.x = legendPos.w - br->pos.w; | |||
| 33869 | ||||
| 33870 | ||||
| 33871 | legendPos.h = bl->pos.y + bl->pos.h - 4; | |||
| 33872 | legendFrame->setSize(legendPos); | |||
| 33873 | ||||
| 33874 | ||||
| 33875 | if ( proficiencyValue < SKILL_LEVEL_LEGENDARY ) | |||
| 33876 | { | |||
| 33877 | legendDivTxt->setTextColor(legendRegularColor); | |||
| 33878 | legendText->setTextColor(legendRegularColor); | |||
| 33879 | ||||
| 33880 | std::string staticImgPath = "*#images/ui/SkillSheet/UI_Skills_LegendBox_Full_"; | |||
| 33881 | staticImgPath += std::to_string(legendPos.w) + 'x' + std::to_string(legendPos.h) + ".png"; | |||
| 33882 | ||||
| 33883 | auto staticImg = Image::get(staticImgPath.c_str()); | |||
| 33884 | if ( staticImg && staticImg->getWidth() > 0 && *cvar_skillsheet_optimise ) | |||
| 33885 | { | |||
| 33886 | for ( auto img : legendFrame->getImages() ) | |||
| 33887 | { | |||
| 33888 | img->disabled = true; | |||
| 33889 | } | |||
| 33890 | mm->disabled = false; | |||
| 33891 | mm->path = staticImgPath; | |||
| 33892 | mm->color = makeColorRGB(255, 255, 255); | |||
| 33893 | mm->pos = SDL_Rect{ 0, 0, legendPos.w, legendPos.h }; | |||
| 33894 | } | |||
| 33895 | else | |||
| 33896 | { | |||
| 33897 | for ( auto img : legendFrame->getImages() ) | |||
| 33898 | { | |||
| 33899 | img->disabled = false; | |||
| 33900 | } | |||
| 33901 | mm->pos.x = 18; | |||
| 33902 | mm->pos.y = 18; | |||
| 33903 | tl->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox_TL_00.png"; | |||
| 33904 | tm->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox_T_00.png"; | |||
| 33905 | tr->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox_TR_00.png"; | |||
| 33906 | ||||
| 33907 | ml->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox_ML_00.png"; | |||
| 33908 | mm->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox_M_00.png"; | |||
| 33909 | mr->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox_MR_00.png"; | |||
| 33910 | ||||
| 33911 | bl->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox_BL_00.png"; | |||
| 33912 | bm->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox_B_00.png"; | |||
| 33913 | br->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox_BR_00.png"; | |||
| 33914 | } | |||
| 33915 | } | |||
| 33916 | else | |||
| 33917 | { | |||
| 33918 | legendDivTxt->setTextColor(legendGoldColor); | |||
| 33919 | legendText->setTextColor(legendGoldColor); | |||
| 33920 | ||||
| 33921 | std::string staticImgPath = "*#images/ui/SkillSheet/UI_Skills_LegendBox100_Full_"; | |||
| 33922 | staticImgPath += std::to_string(legendPos.w) + 'x' + std::to_string(legendPos.h) + ".png"; | |||
| 33923 | ||||
| 33924 | auto staticImg = Image::get(staticImgPath.c_str()); | |||
| 33925 | if ( staticImg && staticImg->getWidth() > 0 && *cvar_skillsheet_optimise ) | |||
| 33926 | { | |||
| 33927 | for ( auto img : legendFrame->getImages() ) | |||
| 33928 | { | |||
| 33929 | img->disabled = true; | |||
| 33930 | } | |||
| 33931 | mm->disabled = false; | |||
| 33932 | mm->path = staticImgPath; | |||
| 33933 | mm->color = makeColorRGB(255, 255, 255); | |||
| 33934 | mm->pos = SDL_Rect{ 0, 0, legendPos.w, legendPos.h }; | |||
| 33935 | } | |||
| 33936 | else | |||
| 33937 | { | |||
| 33938 | for ( auto img : legendFrame->getImages() ) | |||
| 33939 | { | |||
| 33940 | img->disabled = false; | |||
| 33941 | } | |||
| 33942 | mm->pos.x = 18; | |||
| 33943 | mm->pos.y = 18; | |||
| 33944 | tl->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox100_TL_00.png"; | |||
| 33945 | tm->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox100_T_00.png"; | |||
| 33946 | tr->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox100_TR_00.png"; | |||
| 33947 | ||||
| 33948 | ml->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox100_ML_00.png"; | |||
| 33949 | mm->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox100_M_00.png"; | |||
| 33950 | mr->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox100_MR_00.png"; | |||
| 33951 | ||||
| 33952 | bl->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox100_BL_00.png"; | |||
| 33953 | bm->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox100_B_00.png"; | |||
| 33954 | br->path = "*#images/ui/SkillSheet/UI_Skills_LegendBox100_BR_00.png"; | |||
| 33955 | } | |||
| 33956 | } | |||
| 33957 | } | |||
| 33958 | ||||
| 33959 | lowestY = legendPos.y + legendPos.h; | |||
| 33960 | if ( lowestY < scrollAreaOuterFrame->getSize().h ) | |||
| 33961 | { | |||
| 33962 | // shift the legend items as far to the bottom as possible. | |||
| 33963 | int offset = scrollAreaOuterFrame->getSize().h - lowestY; | |||
| 33964 | legendDivImg->pos.y += offset; | |||
| 33965 | legendBackerImg->pos.y += offset; | |||
| 33966 | legendDivTxt->setPos(legendDivTxt->getSize().x, legendDivTxt->getSize().y + offset); | |||
| 33967 | legendFrame->setPos(legendFrame->getSize().x, legendFrame->getSize().y + offset); | |||
| 33968 | } | |||
| 33969 | //lowestY += 4; // small buffer after legend box | |||
| 33970 | } | |||
| 33971 | ||||
| 33972 | auto oldScrollPercent = scrollPercent; | |||
| 33973 | if ( !slider->isDisabled() && player.bControlEnabled && !gamePaused && !player.usingCommand() ) | |||
| 33974 | { | |||
| 33975 | if ( inputs.bPlayerUsingKeyboardControl(player.playernum) ) | |||
| 33976 | { | |||
| 33977 | if ( Input::inputs[player.playernum].binaryToggle("MenuMouseWheelDownAlt") ) | |||
| 33978 | { | |||
| 33979 | //Input::inputs[player.playernum].consumeBinaryToggle("MenuMouseWheelDownAlt"); | |||
| 33980 | scrollInertia = std::min(scrollInertia + .05, .05); | |||
| 33981 | } | |||
| 33982 | if ( Input::inputs[player.playernum].binaryToggle("MenuMouseWheelUpAlt") ) | |||
| 33983 | { | |||
| 33984 | //Input::inputs[player.playernum].consumeBinaryToggle("MenuMouseWheelUpAlt"); | |||
| 33985 | scrollInertia = std::max(scrollInertia - .05, -.05); | |||
| 33986 | } | |||
| 33987 | } | |||
| 33988 | if ( Input::inputs[player.playernum].analog("MenuScrollDown") ) | |||
| 33989 | { | |||
| 33990 | scrollInertia = 0.0; | |||
| 33991 | real_t delta = Input::inputs[player.playernum].analog("MenuScrollDown"); | |||
| 33992 | scrollPercent = std::min(1.0, scrollPercent + .05 * (getFPSScale(60.0)) * delta); | |||
| 33993 | slider->setValue(scrollPercent * 100); | |||
| 33994 | } | |||
| 33995 | else if ( Input::inputs[player.playernum].analog("MenuScrollUp") ) | |||
| 33996 | { | |||
| 33997 | scrollInertia = 0.0; | |||
| 33998 | real_t delta = Input::inputs[player.playernum].analog("MenuScrollUp"); | |||
| 33999 | scrollPercent = std::max(0.0, scrollPercent -.05 * (getFPSScale(60.0)) * delta); | |||
| 34000 | slider->setValue(scrollPercent * 100); | |||
| 34001 | } | |||
| 34002 | } | |||
| 34003 | ||||
| 34004 | if ( abs(scrollInertia) > 0.0 ) | |||
| 34005 | { | |||
| 34006 | scrollInertia *= .9; | |||
| 34007 | if ( abs(scrollInertia) < .01 ) | |||
| 34008 | { | |||
| 34009 | scrollInertia = 0.0; | |||
| 34010 | } | |||
| 34011 | scrollPercent = std::min(1.0, std::max(scrollPercent + scrollInertia, 0.00)); | |||
| 34012 | if ( scrollPercent >= 1.0 || scrollPercent <= 0.0 ) | |||
| 34013 | { | |||
| 34014 | scrollInertia = 0.0; | |||
| 34015 | } | |||
| 34016 | slider->setValue(scrollPercent * 100); | |||
| 34017 | } | |||
| 34018 | ||||
| 34019 | scrollPercent = slider->getValue() / 100.0; | |||
| 34020 | scrollAreaPos = scrollArea->getSize(); | |||
| 34021 | if ( lowestY > scrollAreaOuterFrame->getSize().h ) | |||
| 34022 | { | |||
| 34023 | SDL_Rect actualSize = scrollArea->getActualSize(); | |||
| 34024 | actualSize.y = (lowestY - scrollAreaOuterFrame->getSize().h) * scrollPercent; | |||
| 34025 | actualSize.h = scrollAreaPos.h; | |||
| 34026 | scrollArea->setActualSize(actualSize); | |||
| 34027 | ||||
| 34028 | scrollAreaPos.y = 0; | |||
| 34029 | slider->setDisabled(false); | |||
| 34030 | } | |||
| 34031 | else | |||
| 34032 | { | |||
| 34033 | SDL_Rect actualSize = scrollArea->getActualSize(); | |||
| 34034 | actualSize.y = 0; | |||
| 34035 | scrollArea->setActualSize(actualSize); | |||
| 34036 | ||||
| 34037 | scrollAreaPos.y = 0; | |||
| 34038 | slider->setDisabled(true); | |||
| 34039 | } | |||
| 34040 | if ( scrollPercent != oldScrollPercent ) | |||
| 34041 | { | |||
| 34042 | reblitFrame = true; | |||
| 34043 | } | |||
| 34044 | scrollArea->setSize(scrollAreaPos); | |||
| 34045 | ||||
| 34046 | if ( !slider->isDisabled() && inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 34047 | { | |||
| 34048 | sliderSkillsheetUpdateSelectorOnHighlight(player.playernum, slider); | |||
| 34049 | } | |||
| 34050 | } | |||
| 34051 | ||||
| 34052 | if ( oldHighlightedSkill != highlightedSkill ) | |||
| 34053 | { | |||
| 34054 | reblitFrame = true; | |||
| 34055 | } | |||
| 34056 | ||||
| 34057 | //DebugTimers.addTimePoint("skill", "post display"); | |||
| 34058 | ||||
| 34059 | bool drawGlyphs = !::inputs.getVirtualMouse(player.playernum)->draw_cursor && inputs.hasController(player.playernum); | |||
| 34060 | if ( auto promptBack = skillFrame->findField("prompt back txt") ) | |||
| 34061 | { | |||
| 34062 | promptBack->setDisabled(!drawGlyphs); | |||
| 34063 | promptBack->setText(Language::get(4053)); | |||
| 34064 | auto promptImg = skillFrame->findImage("prompt back img"); | |||
| 34065 | promptImg->disabled = !drawGlyphs; | |||
| 34066 | SDL_Rect glyphPos = promptImg->pos; | |||
| 34067 | if ( auto textGet = Text::get(promptBack->getText(), promptBack->getFont(), | |||
| 34068 | promptBack->getTextColor(), promptBack->getOutlineColor()) ) | |||
| 34069 | { | |||
| 34070 | SDL_Rect textPos = promptBack->getSize(); | |||
| 34071 | textPos.w = textGet->getWidth(); | |||
| 34072 | textPos.x = innerFrame->getSize().x + innerFrame->getSize().w - textPos.w - 16; | |||
| 34073 | textPos.y = innerFrame->getSize().y + allSkillEntriesLeft->getSize().y + lowestSkillEntryY + 4; | |||
| 34074 | if ( !bUseCompactSkillsView ) | |||
| 34075 | { | |||
| 34076 | textPos.y -= 4; | |||
| 34077 | } | |||
| 34078 | promptBack->setSize(textPos); | |||
| 34079 | glyphPos.x = promptBack->getSize().x + promptBack->getSize().w - textGet->getWidth() - 4; | |||
| 34080 | } | |||
| 34081 | promptImg->path = Input::inputs[player.playernum].getGlyphPathForBinding("MenuCancel"); | |||
| 34082 | Image* glyphImage = Image::get(promptImg->path.c_str()); | |||
| 34083 | if ( glyphImage ) | |||
| 34084 | { | |||
| 34085 | glyphPos.w = glyphImage->getWidth(); | |||
| 34086 | glyphPos.h = glyphImage->getHeight(); | |||
| 34087 | glyphPos.x -= glyphPos.w; | |||
| 34088 | glyphPos.y = promptBack->getSize().y + promptBack->getSize().h / 2 - glyphPos.h / 2; | |||
| 34089 | promptImg->pos = glyphPos; | |||
| 34090 | } | |||
| 34091 | } | |||
| 34092 | if ( auto promptScroll = skillFrame->findField("prompt scroll txt") ) | |||
| 34093 | { | |||
| 34094 | promptScroll->setDisabled(!drawGlyphs); | |||
| 34095 | if ( bUseCompactSkillsView ) | |||
| 34096 | { | |||
| 34097 | promptScroll->setText(Language::get(4063)); | |||
| 34098 | } | |||
| 34099 | else | |||
| 34100 | { | |||
| 34101 | promptScroll->setText(Language::get(4062)); | |||
| 34102 | } | |||
| 34103 | auto promptImg = skillFrame->findImage("prompt scroll img"); | |||
| 34104 | promptImg->disabled = !drawGlyphs; | |||
| 34105 | SDL_Rect glyphPos = promptImg->pos; | |||
| 34106 | if ( auto textGet = Text::get(promptScroll->getText(), promptScroll->getFont(), | |||
| 34107 | promptScroll->getTextColor(), promptScroll->getOutlineColor()) ) | |||
| 34108 | { | |||
| 34109 | SDL_Rect textPos = promptScroll->getSize(); | |||
| 34110 | textPos.w = textGet->getWidth(); | |||
| 34111 | if ( bUseCompactSkillsView ) | |||
| 34112 | { | |||
| 34113 | textPos.x = innerFrame->getSize().x + 16; | |||
| 34114 | textPos.y = innerFrame->getSize().y + allSkillEntriesLeft->getSize().y + lowestSkillEntryY + 4; | |||
| 34115 | } | |||
| 34116 | else | |||
| 34117 | { | |||
| 34118 | textPos.x = innerFrame->getSize().x + innerFrame->getSize().w / 2 - textPos.w / 2; | |||
| 34119 | textPos.y = innerFrame->getSize().y + innerFrame->getSize().h - 8; | |||
| 34120 | } | |||
| 34121 | promptScroll->setSize(textPos); | |||
| 34122 | } | |||
| 34123 | promptImg->path = Input::inputs[player.playernum].getGlyphPathForBinding("MenuScrollDown"); | |||
| 34124 | Image* glyphImage = Image::get(promptImg->path.c_str()); | |||
| 34125 | if ( glyphImage ) | |||
| 34126 | { | |||
| 34127 | SDL_Rect textPos = promptScroll->getSize(); | |||
| 34128 | glyphPos.w = glyphImage->getWidth(); | |||
| 34129 | glyphPos.h = glyphImage->getHeight(); | |||
| 34130 | glyphPos.x = textPos.x; | |||
| 34131 | if ( !bUseCompactSkillsView ) // centred | |||
| 34132 | { | |||
| 34133 | glyphPos.x -= glyphPos.w / 2 + 2; | |||
| 34134 | } | |||
| 34135 | glyphPos.y = promptScroll->getSize().y + promptScroll->getSize().h / 2 - glyphPos.h / 2; | |||
| 34136 | promptImg->pos = glyphPos; | |||
| 34137 | ||||
| 34138 | textPos.x = glyphPos.x + glyphPos.w + 4; | |||
| 34139 | promptScroll->setSize(textPos); | |||
| 34140 | } | |||
| 34141 | } | |||
| 34142 | ||||
| 34143 | { | |||
| 34144 | // close btn | |||
| 34145 | auto closeBtn = innerFrame->findButton("close skills button"); | |||
| 34146 | closeBtn->setDisabled(true); | |||
| 34147 | if ( inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 34148 | { | |||
| 34149 | closeBtn->setDisabled(!(skillsFadeInAnimationY >= 0.999)); | |||
| 34150 | closeBtn->setInvisible(false); | |||
| 34151 | if ( !closeBtn->isDisabled() ) | |||
| 34152 | { | |||
| 34153 | buttonSkillsheetUpdateSelectorOnHighlight(player.playernum, closeBtn); | |||
| 34154 | } | |||
| 34155 | } | |||
| 34156 | else | |||
| 34157 | { | |||
| 34158 | closeBtn->setDisabled(true); | |||
| 34159 | closeBtn->setInvisible(true); | |||
| 34160 | if ( closeBtn->isSelected() ) | |||
| 34161 | { | |||
| 34162 | closeBtn->deselect(); | |||
| 34163 | } | |||
| 34164 | } | |||
| 34165 | ||||
| 34166 | SDL_Rect closeBtnPos = closeBtn->getSize(); | |||
| 34167 | SDL_Rect bgImgPos = bgImgFrame->getSize(); | |||
| 34168 | closeBtnPos.x = bgImgPos.x + bgImgPos.w - 38; | |||
| 34169 | closeBtnPos.y = bgImgPos.y + 22; | |||
| 34170 | closeBtn->setSize(closeBtnPos); | |||
| 34171 | } | |||
| 34172 | ||||
| 34173 | if ( closeSheetAction || mouseClickedOutOfBounds ) | |||
| 34174 | { | |||
| 34175 | if ( mouseClickedOutOfBounds ) | |||
| 34176 | { | |||
| 34177 | Input::inputs[player.playernum].consumeBinaryToggle("MenuLeftClick"); | |||
| 34178 | Input::inputs[player.playernum].consumeBindingsSharedWithBinding("MenuLeftClick"); | |||
| 34179 | if ( inputs.bPlayerUsingKeyboardControl(player.playernum) ) | |||
| 34180 | { | |||
| 34181 | mousestatus[SDL_BUTTON_LEFT1] = 0; | |||
| 34182 | } | |||
| 34183 | } | |||
| 34184 | closeSkillSheet(); | |||
| 34185 | Player::soundCancel(); | |||
| 34186 | return; | |||
| 34187 | } | |||
| 34188 | ||||
| 34189 | { | |||
| 34190 | if ( !bSkillSheetEntryLoaded || reblitFrame || skillsFadeInAnimationY < 1.0 ) | |||
| 34191 | { | |||
| 34192 | skillSheetEntryFrames[player.playernum].skillsFrame->setBlitDirty(true); | |||
| 34193 | } | |||
| 34194 | } | |||
| 34195 | ||||
| 34196 | if ( sliderDisabled != slider->isDisabled() ) | |||
| 34197 | { | |||
| 34198 | // rerun this function | |||
| 34199 | processSkillSheet(); | |||
| 34200 | //bSkillSheetEntryLoaded = false; | |||
| 34201 | } | |||
| 34202 | else | |||
| 34203 | { | |||
| 34204 | bSkillSheetEntryLoaded = true; | |||
| 34205 | } | |||
| 34206 | //DebugTimers.addTimePoint("skill", "end"); | |||
| 34207 | //DebugTimers.addTimePoint("skill 1", "end"); | |||
| 34208 | } | |||
| 34209 | ||||
| 34210 | void Player::Inventory_t::SpellPanel_t::openSpellPanel() | |||
| 34211 | { | |||
| 34212 | if ( player.inventoryUI.spellFrame ) | |||
| 34213 | { | |||
| 34214 | bool wasDisabled = player.inventoryUI.spellFrame->isDisabled(); | |||
| 34215 | player.inventoryUI.spellFrame->setDisabled(false); | |||
| 34216 | if ( wasDisabled ) | |||
| 34217 | { | |||
| 34218 | animx = 0.0; | |||
| 34219 | isInteractable = false; | |||
| 34220 | currentScrollRow = 0; | |||
| 34221 | scrollPercent = 0.0; | |||
| 34222 | scrollInertia = 0.0; | |||
| 34223 | bFirstTimeSnapCursor = false; | |||
| 34224 | if ( !inputs.getUIInteraction(player.playernum)->selectedItem ) | |||
| 34225 | { | |||
| 34226 | Player::soundActivate(); | |||
| 34227 | } | |||
| 34228 | } | |||
| 34229 | bOpen = true; | |||
| 34230 | } | |||
| 34231 | } | |||
| 34232 | ||||
| 34233 | void Player::Inventory_t::SpellPanel_t::closeSpellPanel() | |||
| 34234 | { | |||
| 34235 | if ( player.inventoryUI.spellFrame ) | |||
| 34236 | { | |||
| 34237 | player.inventoryUI.spellFrame->setDisabled(true); | |||
| 34238 | } | |||
| 34239 | animx = 0.0; | |||
| 34240 | isInteractable = false; | |||
| 34241 | currentScrollRow = 0; | |||
| 34242 | scrollPercent = 0.0; | |||
| 34243 | scrollInertia = 0.0; | |||
| 34244 | scrollAnimateX = scrollSetpoint; | |||
| 34245 | if ( bOpen | |||
| 34246 | && !(player.inventoryUI.bCompactView | |||
| 34247 | && player.hud.compactLayoutMode == Player::HUD_t::COMPACT_LAYOUT_CHARSHEET) ) | |||
| 34248 | { | |||
| 34249 | if ( !inputs.getUIInteraction(player.playernum)->selectedItem ) | |||
| 34250 | { | |||
| 34251 | Player::soundCancel(); | |||
| 34252 | } | |||
| 34253 | } | |||
| 34254 | bOpen = false; | |||
| 34255 | bFirstTimeSnapCursor = false; | |||
| 34256 | } | |||
| 34257 | ||||
| 34258 | int Player::Inventory_t::SpellPanel_t::getNumSpellsToDisplayVertical() const | |||
| 34259 | { | |||
| 34260 | if ( !player.bUseCompactGUIHeight() ) | |||
| 34261 | { | |||
| 34262 | return kNumSpellsToDisplayVertical; | |||
| 34263 | } | |||
| 34264 | else | |||
| 34265 | { | |||
| 34266 | return kNumSpellsToDisplayVertical; | |||
| 34267 | } | |||
| 34268 | } | |||
| 34269 | ||||
| 34270 | void buttonSpellUpdateSelectorOnHighlight(const int player, Button* button) | |||
| 34271 | { | |||
| 34272 | if ( button->isHighlighted() ) | |||
| 34273 | { | |||
| 34274 | players[player]->GUI.setHoveringOverModuleButton(Player::GUI_t::MODULE_SPELLS); | |||
| 34275 | if ( players[player]->GUI.activeModule != Player::GUI_t::MODULE_SPELLS ) | |||
| 34276 | { | |||
| 34277 | players[player]->GUI.activateModule(Player::GUI_t::MODULE_SPELLS); | |||
| 34278 | } | |||
| 34279 | SDL_Rect pos = button->getAbsoluteSize(); | |||
| 34280 | // make sure to adjust absolute size to camera viewport | |||
| 34281 | pos.x -= players[player]->camera_virtualx1(); | |||
| 34282 | pos.y -= players[player]->camera_virtualy1(); | |||
| 34283 | players[player]->hud.setCursorDisabled(false); | |||
| 34284 | players[player]->hud.updateCursorAnimation(pos.x - 1, pos.y - 1, pos.w, pos.h, inputs.getVirtualMouse(player)->draw_cursor); | |||
| 34285 | } | |||
| 34286 | } | |||
| 34287 | ||||
| 34288 | void sliderSpellUpdateSelectorOnHighlight(const int player, Slider* slider) | |||
| 34289 | { | |||
| 34290 | if ( slider->isHighlighted() ) | |||
| 34291 | { | |||
| 34292 | players[player]->GUI.setHoveringOverModuleButton(Player::GUI_t::MODULE_SPELLS); | |||
| 34293 | if ( players[player]->GUI.activeModule != Player::GUI_t::MODULE_SPELLS ) | |||
| 34294 | { | |||
| 34295 | players[player]->GUI.activateModule(Player::GUI_t::MODULE_SPELLS); | |||
| 34296 | } | |||
| 34297 | SDL_Rect pos = slider->getAbsoluteSize(); | |||
| 34298 | // make sure to adjust absolute size to camera viewport | |||
| 34299 | pos.x -= players[player]->camera_virtualx1(); | |||
| 34300 | pos.y -= players[player]->camera_virtualy1(); | |||
| 34301 | players[player]->hud.setCursorDisabled(false); | |||
| 34302 | players[player]->hud.updateCursorAnimation(pos.x - 1, pos.y - 1, pos.w, pos.h, inputs.getVirtualMouse(player)->draw_cursor); | |||
| 34303 | } | |||
| 34304 | } | |||
| 34305 | ||||
| 34306 | int Player::Inventory_t::SpellPanel_t::heightOffsetWhenNotCompact = 0; | |||
| 34307 | void Player::Inventory_t::SpellPanel_t::updateSpellPanel() | |||
| 34308 | { | |||
| 34309 | Frame* spellFrame = player.inventoryUI.spellFrame; | |||
| 34310 | if ( !spellFrame ) { return; } | |||
| 34311 | ||||
| 34312 | if ( !spellFrame->isDisabled() && bOpen ) | |||
| 34313 | { | |||
| 34314 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 34315 | real_t setpointDiffX = fpsScale * std::max(.01, (1.0 - animx)) / 2.0; | |||
| 34316 | animx += setpointDiffX; | |||
| 34317 | animx = std::min(1.0, animx); | |||
| 34318 | if ( animx >= .9999 ) | |||
| 34319 | { | |||
| 34320 | if ( !bFirstTimeSnapCursor ) | |||
| 34321 | { | |||
| 34322 | bFirstTimeSnapCursor = true; | |||
| 34323 | if ( !inputs.getUIInteraction(player.playernum)->selectedItem | |||
| 34324 | && player.GUI.activeModule == Player::GUI_t::MODULE_SPELLS ) | |||
| 34325 | { | |||
| 34326 | player.inventoryUI.warpMouseToSelectedSpell(nullptr, (Inputs::SET_CONTROLLER)); | |||
| 34327 | } | |||
| 34328 | } | |||
| 34329 | isInteractable = true; | |||
| 34330 | } | |||
| 34331 | } | |||
| 34332 | else | |||
| 34333 | { | |||
| 34334 | animx = 0.0; | |||
| 34335 | isInteractable = false; | |||
| 34336 | scrollInertia = 0.0; | |||
| 34337 | } | |||
| 34338 | auto spellFramePos = spellFrame->getSize(); | |||
| 34339 | if ( player.inventoryUI.inventoryPanelJustify == Player::PANEL_JUSTIFY_LEFT ) | |||
| 34340 | { | |||
| 34341 | spellFramePos.x = -spellFramePos.w + animx * spellFramePos.w; | |||
| 34342 | if ( player.bUseCompactGUIWidth() ) | |||
| 34343 | { | |||
| 34344 | if ( player.inventoryUI.slideOutPercent >= .0001 ) | |||
| 34345 | { | |||
| 34346 | isInteractable = false; | |||
| 34347 | } | |||
| 34348 | spellFramePos.x -= player.inventoryUI.slideOutWidth * player.inventoryUI.slideOutPercent; | |||
| 34349 | } | |||
| 34350 | } | |||
| 34351 | else | |||
| 34352 | { | |||
| 34353 | spellFramePos.x = player.camera_virtualWidth() - animx * spellFramePos.w; | |||
| 34354 | if ( player.bUseCompactGUIWidth() ) | |||
| 34355 | { | |||
| 34356 | if ( player.inventoryUI.slideOutPercent >= .0001 ) | |||
| 34357 | { | |||
| 34358 | isInteractable = false; | |||
| 34359 | } | |||
| 34360 | spellFramePos.x -= -player.inventoryUI.slideOutWidth * player.inventoryUI.slideOutPercent; | |||
| 34361 | } | |||
| 34362 | } | |||
| 34363 | spellFrame->setSize(spellFramePos); | |||
| 34364 | ||||
| 34365 | auto baseFrame = spellFrame->findFrame("spell base"); | |||
| 34366 | auto slider = baseFrame->findSlider("spell slider"); | |||
| 34367 | auto spellSlotsFrame = spellFrame->findFrame("spell slots"); | |||
| 34368 | auto baseBackgroundImg = baseFrame->findImage("spell base img"); | |||
| 34369 | // handle height changing.. | |||
| 34370 | { | |||
| 34371 | int frameHeight = kSpellListHeight; | |||
| 34372 | int totalFrameHeightChange = 0; | |||
| 34373 | if ( !player.bUseCompactGUIHeight() ) | |||
| 34374 | { | |||
| 34375 | totalFrameHeightChange = heightOffsetWhenNotCompact; | |||
| 34376 | } | |||
| 34377 | spellFramePos.h = frameHeight + totalFrameHeightChange; | |||
| 34378 | spellFrame->setSize(spellFramePos); | |||
| 34379 | baseBackgroundImg->pos.y = totalFrameHeightChange; | |||
| 34380 | ||||
| 34381 | SDL_Rect spellBasePos = baseFrame->getSize(); | |||
| 34382 | spellBasePos.h = spellFramePos.h; | |||
| 34383 | baseFrame->setSize(spellBasePos); | |||
| 34384 | ||||
| 34385 | int numGrids = (players[player.playernum]->inventoryUI.MAX_SPELLS_Y / getNumSpellsToDisplayVertical()) + 1; | |||
| 34386 | SDL_Rect spellSlotsFramePos = spellSlotsFrame->getSize(); | |||
| 34387 | ||||
| 34388 | int heightChange = 0; | |||
| 34389 | if ( getNumSpellsToDisplayVertical() < kNumSpellsToDisplayVertical ) | |||
| 34390 | { | |||
| 34391 | heightChange = player.inventoryUI.getSlotSize() * (kNumSpellsToDisplayVertical - getNumSpellsToDisplayVertical()); | |||
| 34392 | } | |||
| 34393 | spellSlotsFramePos.y = 4 + heightChange + totalFrameHeightChange; | |||
| 34394 | spellSlotsFramePos.h = 242 - heightChange; | |||
| 34395 | spellSlotsFrame->setActualSize(SDL_Rect{ spellSlotsFrame->getActualSize().x, | |||
| 34396 | spellSlotsFrame->getActualSize().y, | |||
| 34397 | spellSlotsFrame->getActualSize().w, | |||
| 34398 | (spellSlotsFramePos.h) * numGrids }); | |||
| 34399 | spellSlotsFrame->setSize(spellSlotsFramePos); | |||
| 34400 | auto gridImg = spellSlotsFrame->findImage("grid img"); | |||
| 34401 | gridImg->pos.y = kSpellListGridY; | |||
| 34402 | gridImg->pos.h = (spellSlotsFramePos.h) * numGrids; | |||
| 34403 | ||||
| 34404 | SDL_Rect sliderPos = slider->getRailSize(); | |||
| 34405 | sliderPos.y = 50 + heightChange + totalFrameHeightChange; | |||
| 34406 | sliderPos.h = 192 - heightChange; | |||
| 34407 | slider->setRailSize(sliderPos); | |||
| 34408 | ||||
| 34409 | auto sliderCapTop = baseFrame->findImage("spell slider top"); | |||
| 34410 | auto sliderCapBot = baseFrame->findImage("spell slider bot"); | |||
| 34411 | sliderCapTop->pos.y = sliderPos.y; | |||
| 34412 | sliderCapBot->pos.y = sliderPos.y + sliderPos.h - sliderCapBot->pos.h; | |||
| 34413 | } | |||
| 34414 | ||||
| 34415 | auto skillBg = baseFrame->findImage("spell skill bg"); | |||
| 34416 | skillBg->pos.x = 14; | |||
| 34417 | skillBg->pos.y = 6; | |||
| 34418 | ||||
| 34419 | int lowestItemY = getNumSpellsToDisplayVertical() - 1; | |||
| 34420 | for ( node_t* node = stats[player.playernum]->inventory.first; node != NULL__null; node = node->next ) | |||
| 34421 | { | |||
| 34422 | Item* item = (Item*)node->element; | |||
| 34423 | if ( !item ) { continue; } | |||
| 34424 | if ( itemCategory(item) != SPELL_CAT ) { continue; } | |||
| 34425 | ||||
| 34426 | lowestItemY = std::max(lowestItemY, item->y); | |||
| 34427 | } | |||
| 34428 | ||||
| 34429 | int scrollAmount = std::max((lowestItemY + 1) - (getNumSpellsToDisplayVertical()), 0) * player.inventoryUI.getSlotSize(); | |||
| 34430 | if ( scrollAmount == 0 ) | |||
| 34431 | { | |||
| 34432 | slider->setDisabled(true); | |||
| 34433 | } | |||
| 34434 | else | |||
| 34435 | { | |||
| 34436 | if ( bOpen ) | |||
| 34437 | { | |||
| 34438 | slider->setDisabled(false); | |||
| 34439 | } | |||
| 34440 | else | |||
| 34441 | { | |||
| 34442 | slider->setDisabled(true); | |||
| 34443 | } | |||
| 34444 | } | |||
| 34445 | ||||
| 34446 | currentScrollRow = scrollSetpoint / player.inventoryUI.getSlotSize(); | |||
| 34447 | ||||
| 34448 | bool usingGamepad = inputs.hasController(player.playernum) && !inputs.getVirtualMouse(player.playernum)->draw_cursor; | |||
| 34449 | // close btn | |||
| 34450 | auto closeBtn = baseFrame->findButton("close spell button"); | |||
| 34451 | auto closeGlyph = baseFrame->findImage("close spell glyph"); | |||
| 34452 | closeBtn->setDisabled(true); | |||
| 34453 | SDL_Rect closeBtnPos = closeBtn->getSize(); | |||
| 34454 | closeBtnPos.x = 166; | |||
| 34455 | closeBtnPos.y = 8; | |||
| 34456 | closeBtn->setSize(closeBtnPos); | |||
| 34457 | closeGlyph->disabled = true; | |||
| 34458 | if ( inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 34459 | { | |||
| 34460 | closeBtn->setDisabled(!isInteractable); | |||
| 34461 | if ( isInteractable ) | |||
| 34462 | { | |||
| 34463 | buttonSpellUpdateSelectorOnHighlight(player.playernum, closeBtn); | |||
| 34464 | } | |||
| 34465 | } | |||
| 34466 | else if ( closeBtn->isSelected() ) | |||
| 34467 | { | |||
| 34468 | closeBtn->deselect(); | |||
| 34469 | } | |||
| 34470 | if ( closeBtn->isDisabled() && usingGamepad ) | |||
| 34471 | { | |||
| 34472 | SDL_Rect closeBtnPos = closeBtn->getSize(); | |||
| 34473 | closeBtnPos.x -= 10; | |||
| 34474 | closeBtn->setSize(closeBtnPos); | |||
| 34475 | ||||
| 34476 | closeGlyph->path = Input::inputs[player.playernum].getGlyphPathForBinding("MenuCancel"); | |||
| 34477 | if ( auto imgGet = Image::get(closeGlyph->path.c_str()) ) | |||
| 34478 | { | |||
| 34479 | closeGlyph->pos.w = imgGet->getWidth(); | |||
| 34480 | closeGlyph->pos.h = imgGet->getHeight(); | |||
| 34481 | closeGlyph->disabled = false; | |||
| 34482 | } | |||
| 34483 | closeGlyph->pos.x = closeBtn->getSize().x + closeBtn->getSize().w; | |||
| 34484 | if ( closeGlyph->pos.x % 2 == 1 ) | |||
| 34485 | { | |||
| 34486 | ++closeGlyph->pos.x; | |||
| 34487 | } | |||
| 34488 | closeGlyph->pos.y = closeBtn->getSize().y + closeBtn->getSize().h / 2 - closeGlyph->pos.w / 2; | |||
| 34489 | if ( closeGlyph->pos.y % 2 == 1 ) | |||
| 34490 | { | |||
| 34491 | ++closeGlyph->pos.y; | |||
| 34492 | } | |||
| 34493 | } | |||
| 34494 | ||||
| 34495 | auto skillIcon = baseFrame->findImage("spell skill icon"); | |||
| 34496 | skillIcon->pos.x = skillBg->pos.x + 4; | |||
| 34497 | skillIcon->pos.y = skillBg->pos.y + 4; | |||
| 34498 | for ( auto& skillEntry : Player::SkillSheet_t::skillSheetData.skillEntries ) | |||
| 34499 | { | |||
| 34500 | if ( skillEntry.skillId == PRO_MAGIC ) | |||
| 34501 | { | |||
| 34502 | if ( skillCapstoneUnlocked(player.playernum, PRO_MAGIC) ) | |||
| 34503 | { | |||
| 34504 | skillIcon->path = skillEntry.skillIconPathLegend.c_str(); | |||
| 34505 | } | |||
| 34506 | else | |||
| 34507 | { | |||
| 34508 | skillIcon->path = skillEntry.skillIconPath.c_str(); | |||
| 34509 | } | |||
| 34510 | break; | |||
| 34511 | } | |||
| 34512 | } | |||
| 34513 | ||||
| 34514 | if ( bOpen && isInteractable ) | |||
| 34515 | { | |||
| 34516 | // do sliders | |||
| 34517 | if ( !slider->isDisabled() ) | |||
| 34518 | { | |||
| 34519 | if ( !inputs.getUIInteraction(player.playernum)->selectedItem | |||
| 34520 | && player.GUI.activeModule == Player::GUI_t::MODULE_SPELLS ) | |||
| 34521 | { | |||
| 34522 | auto& input = Input::inputs[player.playernum]; | |||
| 34523 | if ( !player.inventoryUI.itemTooltipDisplay.scrollable ) | |||
| 34524 | { | |||
| 34525 | if ( inputs.bPlayerUsingKeyboardControl(player.playernum) ) | |||
| 34526 | { | |||
| 34527 | if ( input.binaryToggle("MenuMouseWheelDown") ) | |||
| 34528 | { | |||
| 34529 | scrollSetpoint = std::max(scrollSetpoint + player.inventoryUI.getSlotSize(), 0); | |||
| 34530 | } | |||
| 34531 | if ( input.binaryToggle("MenuMouseWheelUp") ) | |||
| 34532 | { | |||
| 34533 | scrollSetpoint = std::max(scrollSetpoint - player.inventoryUI.getSlotSize(), 0); | |||
| 34534 | } | |||
| 34535 | } | |||
| 34536 | ||||
| 34537 | if ( input.consumeBinaryToggle("MenuScrollDown") ) | |||
| 34538 | { | |||
| 34539 | scrollSetpoint = std::max(scrollSetpoint + player.inventoryUI.getSlotSize(), 0); | |||
| 34540 | if ( player.inventoryUI.cursor.queuedModule == Player::GUI_t::MODULE_SPELLS ) | |||
| 34541 | { | |||
| 34542 | player.inventoryUI.cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 34543 | } | |||
| 34544 | } | |||
| 34545 | else if ( input.consumeBinaryToggle("MenuScrollUp") ) | |||
| 34546 | { | |||
| 34547 | scrollSetpoint = std::max(scrollSetpoint - player.inventoryUI.getSlotSize(), 0); | |||
| 34548 | if ( player.inventoryUI.cursor.queuedModule == Player::GUI_t::MODULE_SPELLS ) | |||
| 34549 | { | |||
| 34550 | player.inventoryUI.cursor.queuedModule = Player::GUI_t::MODULE_NONE; | |||
| 34551 | } | |||
| 34552 | } | |||
| 34553 | } | |||
| 34554 | } | |||
| 34555 | } | |||
| 34556 | ||||
| 34557 | scrollSetpoint = std::min(scrollSetpoint, scrollAmount); | |||
| 34558 | currentScrollRow = scrollSetpoint / player.inventoryUI.getSlotSize(); | |||
| 34559 | ||||
| 34560 | if ( abs(scrollSetpoint - scrollAnimateX) > 0.00001 ) | |||
| 34561 | { | |||
| 34562 | isInteractable = false; | |||
| 34563 | player.inventoryUI.tooltipDelayTick = ticks + TICKS_PER_SECOND50 / 10; | |||
| 34564 | const real_t fpsScale = getFPSScale(60.0); | |||
| 34565 | real_t setpointDiff = 0.0; | |||
| 34566 | ||||
| 34567 | // slightly faster on gamepad | |||
| 34568 | static ConsoleVariable<float> cvar_spell_slider_speed("/spell_slider_speed", 1.f); | |||
| 34569 | const real_t factor = (3.0 * (*cvar_spell_slider_speed + (usingGamepad ? -.25f : 0.f))); | |||
| 34570 | if ( scrollSetpoint - scrollAnimateX > 0.0 ) | |||
| 34571 | { | |||
| 34572 | setpointDiff = fpsScale * std::max(3.0, (scrollSetpoint - scrollAnimateX)) / factor; | |||
| 34573 | } | |||
| 34574 | else | |||
| 34575 | { | |||
| 34576 | setpointDiff = fpsScale * std::min(-3.0, (scrollSetpoint - scrollAnimateX)) / factor; | |||
| 34577 | } | |||
| 34578 | scrollAnimateX += setpointDiff; | |||
| 34579 | if ( setpointDiff > 0.0 ) | |||
| 34580 | { | |||
| 34581 | scrollAnimateX = std::min((real_t)scrollSetpoint, scrollAnimateX); | |||
| 34582 | } | |||
| 34583 | else | |||
| 34584 | { | |||
| 34585 | scrollAnimateX = std::max((real_t)scrollSetpoint, scrollAnimateX); | |||
| 34586 | } | |||
| 34587 | } | |||
| 34588 | else | |||
| 34589 | { | |||
| 34590 | scrollAnimateX = scrollSetpoint; | |||
| 34591 | } | |||
| 34592 | ||||
| 34593 | if ( !inputs.getUIInteraction(player.playernum)->selectedItem | |||
| 34594 | && !player.GUI.isDropdownActive() | |||
| 34595 | && player.GUI.bModuleAccessibleWithMouse(Player::GUI_t::MODULE_SPELLS) | |||
| 34596 | && player.bControlEnabled && !gamePaused && !player.usingCommand() ) | |||
| 34597 | { | |||
| 34598 | if ( Input::inputs[player.playernum].binaryToggle("MenuCancel") ) | |||
| 34599 | { | |||
| 34600 | Input::inputs[player.playernum].consumeBinaryToggle("MenuCancel"); | |||
| 34601 | player.GUI.activateModule(Player::GUI_t::MODULE_SPELLS); | |||
| 34602 | player.inventoryUI.cycleInventoryTab(); | |||
| 34603 | player.inventoryUI.spellPanel.closeSpellPanel(); | |||
| 34604 | } | |||
| 34605 | } | |||
| 34606 | } | |||
| 34607 | ||||
| 34608 | if ( scrollAmount > 0 ) | |||
| 34609 | { | |||
| 34610 | if ( !slider->isDisabled() && !usingGamepad && isInteractable ) | |||
| 34611 | { | |||
| 34612 | sliderSpellUpdateSelectorOnHighlight(player.playernum, slider); | |||
| 34613 | } | |||
| 34614 | if ( slider->isCurrentlyPressed() ) | |||
| 34615 | { | |||
| 34616 | auto val = slider->getValue() / 100.0; | |||
| 34617 | int animX = val * scrollAmount; | |||
| 34618 | animX /= player.inventoryUI.getSlotSize(); | |||
| 34619 | animX *= player.inventoryUI.getSlotSize(); | |||
| 34620 | ||||
| 34621 | scrollSetpoint = animX; | |||
| 34622 | scrollSetpoint = std::min(scrollSetpoint, scrollAmount); | |||
| 34623 | } | |||
| 34624 | else | |||
| 34625 | { | |||
| 34626 | slider->setValue((scrollAnimateX / scrollAmount) * 100.0); | |||
| 34627 | } | |||
| 34628 | } | |||
| 34629 | else | |||
| 34630 | { | |||
| 34631 | slider->setValue(0.0); | |||
| 34632 | } | |||
| 34633 | ||||
| 34634 | SDL_Rect actualSize = spellSlotsFrame->getActualSize(); | |||
| 34635 | actualSize.y = scrollAnimateX; | |||
| 34636 | spellSlotsFrame->setActualSize(actualSize); | |||
| 34637 | } | |||
| 34638 | ||||
| 34639 | bool Player::Inventory_t::SpellPanel_t::isSlotVisible(int x, int y) const | |||
| 34640 | { | |||
| 34641 | if ( player.inventoryUI.spellFrame ) | |||
| 34642 | { | |||
| 34643 | if ( player.inventoryUI.spellFrame->isDisabled() ) | |||
| 34644 | { | |||
| 34645 | return false; | |||
| 34646 | } | |||
| 34647 | } | |||
| 34648 | int lowerY = currentScrollRow; | |||
| 34649 | int upperY = currentScrollRow + getNumSpellsToDisplayVertical() - 1; | |||
| 34650 | ||||
| 34651 | if ( y >= lowerY && y <= upperY ) | |||
| 34652 | { | |||
| 34653 | return true; | |||
| 34654 | } | |||
| 34655 | return false; | |||
| 34656 | } | |||
| 34657 | ||||
| 34658 | bool Player::Inventory_t::SpellPanel_t::isItemVisible(Item* item) const | |||
| 34659 | { | |||
| 34660 | if ( !item ) { return false; } | |||
| 34661 | return isSlotVisible(item->x, item->y); | |||
| 34662 | } | |||
| 34663 | ||||
| 34664 | void Player::Inventory_t::SpellPanel_t::scrollToSlot(int x, int y, bool instantly) | |||
| 34665 | { | |||
| 34666 | int lowerY = currentScrollRow; | |||
| 34667 | int upperY = currentScrollRow + getNumSpellsToDisplayVertical() - 1; | |||
| 34668 | ||||
| 34669 | if ( y >= lowerY && y <= upperY ) | |||
| 34670 | { | |||
| 34671 | // no work to do. | |||
| 34672 | return; | |||
| 34673 | } | |||
| 34674 | ||||
| 34675 | int lowestItemY = getNumSpellsToDisplayVertical() - 1; | |||
| 34676 | for ( node_t* node = stats[player.playernum]->inventory.first; node != NULL__null; node = node->next ) | |||
| 34677 | { | |||
| 34678 | Item* item = (Item*)node->element; | |||
| 34679 | if ( !item ) { continue; } | |||
| 34680 | if ( itemCategory(item) != SPELL_CAT ) { continue; } | |||
| 34681 | ||||
| 34682 | lowestItemY = std::max(lowestItemY, item->y); | |||
| 34683 | } | |||
| 34684 | int maxScroll = std::max((lowestItemY + 1) - (getNumSpellsToDisplayVertical()), 0) * player.inventoryUI.getSlotSize(); | |||
| 34685 | ||||
| 34686 | int scrollAmount = 0; | |||
| 34687 | if ( y < lowerY ) | |||
| 34688 | { | |||
| 34689 | scrollAmount = (y) * player.inventoryUI.getSlotSize(); | |||
| 34690 | //scrollAmount += scrollSetpoint; | |||
| 34691 | } | |||
| 34692 | else if ( y > upperY ) | |||
| 34693 | { | |||
| 34694 | scrollAmount = (y - upperY) * player.inventoryUI.getSlotSize(); | |||
| 34695 | scrollAmount += scrollSetpoint; | |||
| 34696 | } | |||
| 34697 | scrollAmount = std::min(scrollAmount, maxScroll); | |||
| 34698 | ||||
| 34699 | scrollSetpoint = scrollAmount; | |||
| 34700 | if ( instantly ) | |||
| 34701 | { | |||
| 34702 | scrollAnimateX = scrollSetpoint; | |||
| 34703 | } | |||
| 34704 | currentScrollRow = scrollSetpoint / player.inventoryUI.getSlotSize(); | |||
| 34705 | if ( abs(scrollSetpoint - scrollAnimateX) > 0.00001 ) | |||
| 34706 | { | |||
| 34707 | isInteractable = false; | |||
| 34708 | } | |||
| 34709 | } | |||
| 34710 | ||||
| 34711 | void Player::Inventory_t::ChestGUI_t::openChest() | |||
| 34712 | { | |||
| 34713 | if ( player.inventoryUI.chestFrame ) | |||
| 34714 | { | |||
| 34715 | bool wasDisabled = player.inventoryUI.chestFrame->isDisabled(); | |||
| 34716 | player.inventoryUI.chestFrame->setDisabled(false); | |||
| 34717 | if ( wasDisabled ) | |||
| 34718 | { | |||
| 34719 | animx = 0.0; | |||
| 34720 | isInteractable = false; | |||
| 34721 | currentScrollRow = 0; | |||
| 34722 | scrollPercent = 0.0; | |||
| 34723 | scrollInertia = 0.0; | |||
| 34724 | bFirstTimeSnapCursor = false; | |||
| 34725 | } | |||
| 34726 | /*if ( player.inventoryUI.getSelectedChestX() < 0 || player.inventoryUI.getSelectedChestX() >= MAX_CHEST_X | |||
| 34727 | || player.inventoryUI.getSelectedChestY() < 0 || player.inventoryUI.getSelectedChestY() >= MAX_CHEST_Y )*/ | |||
| 34728 | { | |||
| 34729 | player.inventoryUI.selectChestSlot(0, 0); // always select first slot | |||
| 34730 | } | |||
| 34731 | player.hud.compactLayoutMode = Player::HUD_t::COMPACT_LAYOUT_INVENTORY; | |||
| 34732 | player.inventory_mode = INVENTORY_MODE_ITEM; | |||
| 34733 | bOpen = true; | |||
| 34734 | } | |||
| 34735 | if ( inputs.getUIInteraction(player.playernum)->selectedItem ) | |||
| 34736 | { | |||
| 34737 | inputs.getUIInteraction(player.playernum)->selectedItem = nullptr; | |||
| 34738 | inputs.getUIInteraction(player.playernum)->toggleclick = false; | |||
| 34739 | } | |||
| 34740 | inputs.getUIInteraction(player.playernum)->selectedItemFromChest = 0; | |||
| 34741 | } | |||
| 34742 | ||||
| 34743 | bool Player::Inventory_t::ChestGUI_t::isChestSelected() | |||
| 34744 | { | |||
| 34745 | if ( !bOpen ) | |||
| 34746 | { | |||
| 34747 | return false; | |||
| 34748 | } | |||
| 34749 | ||||
| 34750 | if ( player.GUI.activeModule == Player::GUI_t::MODULE_CHEST ) | |||
| 34751 | { | |||
| 34752 | if ( selectedChestSlotX >= 0 && selectedChestSlotX < MAX_CHEST_X | |||
| 34753 | && selectedChestSlotY >= 0 && selectedChestSlotY < MAX_CHEST_Y ) | |||
| 34754 | { | |||
| 34755 | return true; | |||
| 34756 | } | |||
| 34757 | } | |||
| 34758 | ||||
| 34759 | return false; | |||
| 34760 | } | |||
| 34761 | ||||
| 34762 | void Player::Inventory_t::ChestGUI_t::closeChest() | |||
| 34763 | { | |||
| 34764 | if ( player.inventoryUI.chestFrame ) | |||
| 34765 | { | |||
| 34766 | player.inventoryUI.chestFrame->setDisabled(true); | |||
| 34767 | } | |||
| 34768 | animx = 0.0; | |||
| 34769 | isInteractable = false; | |||
| 34770 | currentScrollRow = 0; | |||
| 34771 | scrollPercent = 0.0; | |||
| 34772 | scrollInertia = 0.0; | |||
| 34773 | scrollAnimateX = scrollSetpoint; | |||
| 34774 | bOpen = false; | |||
| 34775 | bFirstTimeSnapCursor = false; | |||
| 34776 | if ( inputs.getUIInteraction(player.playernum)->selectedItemFromChest > 0 ) | |||
| 34777 | { | |||
| 34778 | inputs.getUIInteraction(player.playernum)->selectedItem = nullptr; | |||
| 34779 | inputs.getUIInteraction(player.playernum)->toggleclick = false; | |||
| 34780 | } | |||
| 34781 | inputs.getUIInteraction(player.playernum)->selectedItemFromChest = 0; | |||
| 34782 | if ( player.GUI.dropdownMenu.currentName == "chest_interact" ) | |||
| 34783 | { | |||
| 34784 | player.GUI.dropdownMenu.close(); | |||
| 34785 | } | |||
| 34786 | if ( players[player.playernum]->GUI.activeModule == Player::GUI_t::MODULE_CHEST | |||
| 34787 | && !players[player.playernum]->shootmode ) | |||
| 34788 | { | |||
| 34789 | // reset to inventory mode if still hanging in chest GUI | |||
| 34790 | players[player.playernum]->hud.compactLayoutMode = Player::HUD_t::COMPACT_LAYOUT_INVENTORY; | |||
| 34791 | players[player.playernum]->GUI.activateModule(Player::GUI_t::MODULE_INVENTORY); | |||
| 34792 | if ( !inputs.getVirtualMouse(player.playernum)->draw_cursor ) | |||
| 34793 | { | |||
| 34794 | players[player.playernum]->GUI.warpControllerToModule(false); | |||
| 34795 | } | |||
| 34796 | } | |||
| 34797 | } | |||
| 34798 | ||||
| 34799 | int Player::Inventory_t::ChestGUI_t::getNumItemsToDisplayVertical() const | |||
| 34800 | { | |||
| 34801 | return kNumItemsToDisplayVertical; | |||
| 34802 | } | |||
| 34803 | ||||
| 34804 | void Player::Inventory_t::selectChestSlot(const int x, const int y) | |||
| 34805 | { | |||
| 34806 | chestGUI.selectedChestSlotX = x; | |||
| 34807 | chestGUI.selectedChestSlotY = y; | |||
| 34808 | } | |||
| 34809 | ||||
| 34810 | const bool Player::Inventory_t::isItemFromChest(Item* item) const | |||
| 34811 | { | |||
| 34812 | if ( !item ) | |||
| 34813 | { | |||
| 34814 | return false; | |||
| 34815 | } | |||
| 34816 | ||||
| 34817 | if ( !openedChest[player.playernum] || !chestGUI.bOpen ) | |||
| 34818 | { | |||
| 34819 | return false; | |||
| 34820 | } | |||
| 34821 | ||||
| 34822 | list_t* chest_inventory = nullptr; | |||
| 34823 | if ( multiplayer == CLIENT2 ) | |||
| 34824 | { | |||
| 34825 | chest_inventory = &chestInv[player.playernum]; | |||
| 34826 | } | |||
| 34827 | else if ( openedChest[player.playernum]->children.first && openedChest[player.playernum]->children.first->element ) | |||
| 34828 | { | |||
| 34829 | chest_inventory = (list_t*)openedChest[player.playernum]->children.first->element; | |||
| 34830 | } | |||
| 34831 | ||||
| 34832 | if ( item->node && item->node->list == chest_inventory ) | |||
| 34833 | { | |||
| 34834 | return true; | |||
| 34835 | } | |||
| 34836 | return false; | |||
| 34837 | } | |||
| 34838 | ||||
| 34839 | int Player::Inventory_t::ChestGUI_t::heightOffsetWhenNotCompact = 0; | |||
| 34840 | void Player::Inventory_t::ChestGUI_t::updateChest() | |||
| 34841 | { | |||
| 34842 | updateChestInventory(player.playernum); | |||
| 34843 | ||||
| 34844 | Frame* chestFrame = player.inventoryUI.chestFrame; | |||
| 34845 | if ( !chestFrame ) { return; } | |||
| 34846 | ||||
| 34847 | auto baseFrame = chestFrame->findFrame("chest base"); | |||
| 34848 | auto grabAllBtn = baseFrame->findButton("grab all button"); | |||
| 34849 | auto closeBtn = baseFrame->findButton("close chest button"); | |||
| 34850 | if ( !chestFrame->isDisabled() && bOpen ) | |||
| 34851 | { | |||
| 34852 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 34853 | real_t setpointDiffX = fpsScale * std::max(.01, (1.0 - animx)) / 2.0; | |||
| 34854 | animx += setpointDiffX; | |||
| 34855 | animx = std::min(1.0, animx); | |||
| 34856 | if ( animx >= .9999 ) | |||
| 34857 | { | |||
| 34858 | if ( !bFirstTimeSnapCursor ) | |||
| 34859 | { | |||
| 34860 | bFirstTimeSnapCursor = true; | |||
| 34861 | if ( !inputs.getUIInteraction(player.playernum)->selectedItem | |||
| 34862 | && player.GUI.activeModule == Player::GUI_t::MODULE_CHEST ) | |||
| 34863 | { | |||
| 34864 | player.inventoryUI.warpMouseToSelectedChestSlot(nullptr, (Inputs::SET_CONTROLLER)); | |||
| 34865 | } | |||
| 34866 | } | |||
| 34867 | isInteractable = true; | |||
| 34868 | } | |||
| 34869 | } | |||
| 34870 | else | |||
| 34871 | { | |||
| 34872 | animx = 0.0; | |||
| 34873 | isInteractable = false; | |||
| 34874 | scrollInertia = 0.0; | |||
| 34875 | } | |||
| 34876 | ||||
| 34877 | auto chestFramePos = chestFrame->getSize(); | |||
| 34878 | auto baseBackgroundImg = baseFrame->findImage("chest base img"); | |||
| 34879 | auto lidBackgroundImg = baseFrame->findImage("chest lid img"); | |||
| 34880 | ||||
| 34881 | int playercount = 0; | |||
| 34882 | for ( int c = 0; c < MAXPLAYERS4; ++c ) { | |||
| 34883 | if ( !client_disconnected[c] && players[c]->isLocalPlayer() ) { | |||
| 34884 | ++playercount; | |||
| 34885 | } | |||
| 34886 | } | |||
| 34887 | ||||
| 34888 | if ( player.inventoryUI.inventoryPanelJustify == Player::PANEL_JUSTIFY_LEFT ) | |||
| 34889 | { | |||
| 34890 | if ( !player.inventoryUI.bCompactView ) | |||
| 34891 | { | |||
| 34892 | const int fullWidth = chestFramePos.w + 210; // inventory width 210 | |||
| 34893 | chestFramePos.x = -chestFramePos.w + animx * fullWidth; | |||
| 34894 | if ( player.bUseCompactGUIWidth() ) | |||
| 34895 | { | |||
| 34896 | if ( player.inventoryUI.slideOutPercent >= .0001 ) | |||
| 34897 | { | |||
| 34898 | isInteractable = false; | |||
| 34899 | } | |||
| 34900 | chestFramePos.x -= player.inventoryUI.slideOutWidth * player.inventoryUI.slideOutPercent; | |||
| 34901 | } | |||
| 34902 | } | |||
| 34903 | else | |||
| 34904 | { | |||
| 34905 | if ( player.bAlignGUINextToInventoryCompact() ) | |||
| 34906 | { | |||
| 34907 | const int fullWidth = chestFramePos.w + 210; // inventory width 210 | |||
| 34908 | chestFramePos.x = -chestFramePos.w + animx * fullWidth; | |||
| 34909 | } | |||
| 34910 | else | |||
| 34911 | { | |||
| 34912 | chestFramePos.x = player.camera_virtualWidth() - animx * chestFramePos.w; | |||
| 34913 | } | |||
| 34914 | if ( player.bUseCompactGUIWidth() ) | |||
| 34915 | { | |||
| 34916 | if ( player.inventoryUI.slideOutPercent >= .0001 ) | |||
| 34917 | { | |||
| 34918 | isInteractable = false; | |||
| 34919 | } | |||
| 34920 | chestFramePos.x -= -player.inventoryUI.slideOutWidth * player.inventoryUI.slideOutPercent; | |||
| 34921 | } | |||
| 34922 | } | |||
| 34923 | } | |||
| 34924 | else if ( player.inventoryUI.inventoryPanelJustify == Player::PANEL_JUSTIFY_RIGHT ) | |||
| 34925 | { | |||
| 34926 | if ( !player.inventoryUI.bCompactView ) | |||
| 34927 | { | |||
| 34928 | chestFramePos.x = player.camera_virtualWidth() - animx * chestFramePos.w * 2; | |||
| 34929 | if ( player.bUseCompactGUIWidth() ) | |||
| 34930 | { | |||
| 34931 | if ( player.inventoryUI.slideOutPercent >= .0001 ) | |||
| 34932 | { | |||
| 34933 | isInteractable = false; | |||
| 34934 | } | |||
| 34935 | chestFramePos.x -= -player.inventoryUI.slideOutWidth * player.inventoryUI.slideOutPercent; | |||
| 34936 | } | |||
| 34937 | } | |||
| 34938 | else | |||
| 34939 | { | |||
| 34940 | if ( player.bAlignGUINextToInventoryCompact() ) | |||
| 34941 | { | |||
| 34942 | const int fullWidth = chestFramePos.w + 210; // inventory width 210 | |||
| 34943 | chestFramePos.x = player.camera_virtualWidth() - animx * fullWidth; | |||
| 34944 | } | |||
| 34945 | else | |||
| 34946 | { | |||
| 34947 | chestFramePos.x = -chestFramePos.w + animx * chestFramePos.w; | |||
| 34948 | } | |||
| 34949 | if ( player.bUseCompactGUIWidth() ) | |||
| 34950 | { | |||
| 34951 | if ( player.inventoryUI.slideOutPercent >= .0001 ) | |||
| 34952 | { | |||
| 34953 | isInteractable = false; | |||
| 34954 | } | |||
| 34955 | chestFramePos.x -= player.inventoryUI.slideOutWidth * player.inventoryUI.slideOutPercent; | |||
| 34956 | } | |||
| 34957 | } | |||
| 34958 | } | |||
| 34959 | chestFrame->setSize(chestFramePos); | |||
| 34960 | ||||
| 34961 | bool drawGlyphs = !::inputs.getVirtualMouse(player.playernum)->draw_cursor; | |||
| 34962 | if ( !drawGlyphs ) | |||
| 34963 | { | |||
| 34964 | closeBtn->setInvisible(false); | |||
| 34965 | grabAllBtn->setInvisible(false); | |||
| 34966 | grabAllBtn->setDisabled(!isInteractable); | |||
| 34967 | closeBtn->setDisabled(!isInteractable); | |||
| 34968 | } | |||
| 34969 | else | |||
| 34970 | { | |||
| 34971 | closeBtn->setInvisible(false); | |||
| 34972 | grabAllBtn->setInvisible(false); | |||
| 34973 | grabAllBtn->setDisabled(!isInteractable); | |||
| 34974 | closeBtn->setDisabled(!isInteractable); | |||
| 34975 | } | |||
| 34976 | ||||
| 34977 | //auto slider = baseFrame->findSlider("chest slider"); | |||
| 34978 | auto chestSlotsFrame = chestFrame->findFrame("chest slots"); | |||
| 34979 | ||||
| 34980 | auto promptBack = baseFrame->findField("prompt back txt"); | |||
| 34981 | promptBack->setDisabled(true); | |||
| 34982 | auto promptBackImg = baseFrame->findImage("prompt back img"); | |||
| 34983 | promptBackImg->disabled = !drawGlyphs || player.inventoryUI.spellPanel.bOpen; | |||
| 34984 | auto promptGrab = baseFrame->findField("prompt grab txt"); | |||
| 34985 | promptGrab->setDisabled(true); | |||
| 34986 | auto promptGrabImg = baseFrame->findImage("prompt grab img"); | |||
| 34987 | promptGrabImg->disabled = !drawGlyphs || player.inventoryUI.spellPanel.bOpen; | |||
| 34988 | // handle height changing.. | |||
| 34989 | { | |||
| 34990 | int frameHeight = 236 + 16; | |||
| 34991 | if ( !player.bUseCompactGUIHeight() && !player.bUseCompactGUIWidth() ) | |||
| 34992 | { | |||
| 34993 | chestFramePos.y = 130; | |||
| 34994 | } | |||
| 34995 | else | |||
| 34996 | { | |||
| 34997 | chestFramePos.y = 0; | |||
| 34998 | } | |||
| 34999 | chestFramePos.h = frameHeight; | |||
| 35000 | chestFrame->setSize(chestFramePos); | |||
| 35001 | baseBackgroundImg->pos.y = 16 + 48; | |||
| 35002 | lidBackgroundImg->pos.y = baseBackgroundImg->pos.y - lidBackgroundImg->pos.h + 2; | |||
| 35003 | SDL_Rect chestBasePos = baseFrame->getSize(); | |||
| 35004 | chestBasePos.h = chestFramePos.h; | |||
| 35005 | baseFrame->setSize(chestBasePos); | |||
| 35006 | ||||
| 35007 | int numGrids = (players[player.playernum]->inventoryUI.MAX_CHEST_Y / getNumItemsToDisplayVertical()) + 1; | |||
| 35008 | SDL_Rect chestSlotsFramePos = chestSlotsFrame->getSize(); | |||
| 35009 | ||||
| 35010 | const int gridHeight = 120 + 2; // 120px is grid img, plus 2px to tile the image for bottom border. | |||
| 35011 | ||||
| 35012 | int heightChange = 0; | |||
| 35013 | if ( getNumItemsToDisplayVertical() < kNumItemsToDisplayVertical ) | |||
| 35014 | { | |||
| 35015 | heightChange = player.inventoryUI.getSlotSize() * (kNumItemsToDisplayVertical - getNumItemsToDisplayVertical()); | |||
| 35016 | } | |||
| 35017 | chestSlotsFramePos.y = 4 + chestBaseImgBorderTopHeight + heightChange + 48; | |||
| 35018 | chestSlotsFramePos.h = gridHeight - heightChange; | |||
| 35019 | chestSlotsFrame->setActualSize(SDL_Rect{ chestSlotsFrame->getActualSize().x, | |||
| 35020 | chestSlotsFrame->getActualSize().y, | |||
| 35021 | chestSlotsFrame->getActualSize().w, | |||
| 35022 | (chestSlotsFramePos.h) * numGrids }); | |||
| 35023 | chestSlotsFrame->setSize(chestSlotsFramePos); | |||
| 35024 | //auto gridImg = chestSlotsFrame->findImage("grid img"); | |||
| 35025 | //gridImg->pos.y = 0; | |||
| 35026 | //gridImg->pos.h = (chestSlotsFramePos.h) * numGrids; | |||
| 35027 | ||||
| 35028 | /*SDL_Rect sliderPos = slider->getRailSize(); | |||
| 35029 | sliderPos.y = 8 + heightChange + totalFrameHeightChange; | |||
| 35030 | sliderPos.h = 234 - heightChange; | |||
| 35031 | slider->setRailSize(sliderPos);*/ | |||
| 35032 | ||||
| 35033 | // align title | |||
| 35034 | auto titleText = baseFrame->findField("title txt"); | |||
| 35035 | auto titlePos = titleText->getSize(); | |||
| 35036 | titlePos.y = baseBackgroundImg->pos.y - 24; | |||
| 35037 | titlePos.x = baseBackgroundImg->pos.x + baseBackgroundImg->pos.w / 2 - titlePos.w / 2; | |||
| 35038 | titleText->setSize(titlePos); | |||
| 35039 | ||||
| 35040 | chestFrame->setSize(chestFramePos); | |||
| 35041 | baseFrame->setSize(chestBasePos); | |||
| 35042 | ||||
| 35043 | // align buttons | |||
| 35044 | auto grabAllBtnPos = grabAllBtn->getSize(); | |||
| 35045 | auto bg = baseFrame->findImage("chest base img"); | |||
| 35046 | grabAllBtnPos.y = bg->pos.y + bg->pos.h - 4 - grabAllBtnPos.h - 4; | |||
| 35047 | grabAllBtnPos.x = bg->pos.x + bg->pos.w / 2 - grabAllBtnPos.w / 2; | |||
| 35048 | grabAllBtn->setSize(grabAllBtnPos); | |||
| 35049 | ||||
| 35050 | auto closeBtnPos = closeBtn->getSize(); | |||
| 35051 | closeBtnPos.x = bg->pos.x + bg->pos.w - closeBtnPos.w - 8 - 4; | |||
| 35052 | closeBtnPos.y = titlePos.y + titlePos.h / 2 - closeBtnPos.h / 2; | |||
| 35053 | closeBtn->setSize(closeBtnPos); | |||
| 35054 | ||||
| 35055 | ||||
| 35056 | if ( player.GUI.bModuleAccessibleWithMouse(Player::GUI_t::MODULE_CHEST) | |||
| 35057 | && inputs.getVirtualMouse(player.playernum)->draw_cursor && !drawGlyphs ) | |||
| 35058 | { | |||
| 35059 | if ( !grabAllBtn->isDisabled() && grabAllBtn->isHighlighted() ) | |||
| 35060 | { | |||
| 35061 | player.GUI.setHoveringOverModuleButton(Player::GUI_t::MODULE_CHEST); | |||
| 35062 | if ( player.GUI.activeModule != Player::GUI_t::MODULE_CHEST ) | |||
| 35063 | { | |||
| 35064 | player.GUI.activateModule(Player::GUI_t::MODULE_CHEST); | |||
| 35065 | } | |||
| 35066 | SDL_Rect pos = grabAllBtn->getAbsoluteSize(); | |||
| 35067 | // make sure to adjust absolute size to camera viewport | |||
| 35068 | pos.x -= player.camera_virtualx1(); | |||
| 35069 | pos.y -= player.camera_virtualy1(); | |||
| 35070 | player.hud.setCursorDisabled(false); | |||
| 35071 | player.hud.updateCursorAnimation(pos.x - 1, pos.y - 1, pos.w, pos.h, inputs.getVirtualMouse(player.playernum)->draw_cursor); | |||
| 35072 | } | |||
| 35073 | if ( !closeBtn->isDisabled() && closeBtn->isHighlighted() ) | |||
| 35074 | { | |||
| 35075 | player.GUI.setHoveringOverModuleButton(Player::GUI_t::MODULE_CHEST); | |||
| 35076 | if ( player.GUI.activeModule != Player::GUI_t::MODULE_CHEST ) | |||
| 35077 | { | |||
| 35078 | player.GUI.activateModule(Player::GUI_t::MODULE_CHEST); | |||
| 35079 | } | |||
| 35080 | SDL_Rect pos = closeBtn->getAbsoluteSize(); | |||
| 35081 | // make sure to adjust absolute size to camera viewport | |||
| 35082 | pos.x -= player.camera_virtualx1(); | |||
| 35083 | pos.y -= player.camera_virtualy1(); | |||
| 35084 | player.hud.setCursorDisabled(false); | |||
| 35085 | player.hud.updateCursorAnimation(pos.x - 1, pos.y - 1, pos.w, pos.h, inputs.getVirtualMouse(player.playernum)->draw_cursor); | |||
| 35086 | } | |||
| 35087 | } | |||
| 35088 | ||||
| 35089 | int furthestLeftPrompt = xres; | |||
| 35090 | if ( !promptBack->isDisabled() ) | |||
| 35091 | { | |||
| 35092 | promptBack->setText(Language::get(4053)); | |||
| 35093 | SDL_Rect glyphPos = promptBackImg->pos; | |||
| 35094 | if ( auto textGet = Text::get(promptBack->getText(), promptBack->getFont(), | |||
| 35095 | promptBack->getTextColor(), promptBack->getOutlineColor()) ) | |||
| 35096 | { | |||
| 35097 | SDL_Rect textPos = promptBack->getSize(); | |||
| 35098 | textPos.w = textGet->getWidth(); | |||
| 35099 | textPos.x = bg->pos.x + bg->pos.w - textPos.w - 8; | |||
| 35100 | textPos.y = bg->pos.y + bg->pos.h - textPos.h + 8 + 8; | |||
| 35101 | promptBack->setSize(textPos); | |||
| 35102 | glyphPos.x = promptBack->getSize().x + promptBack->getSize().w - textGet->getWidth() - 4; | |||
| 35103 | } | |||
| 35104 | promptBackImg->path = Input::inputs[player.playernum].getGlyphPathForBinding("MenuCancel"); | |||
| 35105 | Image* glyphImage = Image::get(promptBackImg->path.c_str()); | |||
| 35106 | if ( glyphImage ) | |||
| 35107 | { | |||
| 35108 | glyphPos.w = glyphImage->getWidth(); | |||
| 35109 | glyphPos.h = glyphImage->getHeight(); | |||
| 35110 | glyphPos.x -= glyphPos.w; | |||
| 35111 | furthestLeftPrompt = std::min(glyphPos.x + glyphPos.w / 2, furthestLeftPrompt); | |||
| 35112 | glyphPos.y = promptBack->getSize().y + promptBack->getSize().h / 2 - glyphPos.h / 2; | |||
| 35113 | promptBackImg->pos = glyphPos; | |||
| 35114 | } | |||
| 35115 | } | |||
| 35116 | else if ( drawGlyphs ) | |||
| 35117 | { | |||
| 35118 | SDL_Rect glyphPos = closeBtn->getSize(); | |||
| 35119 | //glyphPos.x += glyphPos.w / 2; | |||
| 35120 | promptBackImg->path = Input::inputs[player.playernum].getGlyphPathForBinding("MenuCancel"); | |||
| 35121 | promptBackImg->ontop = true; | |||
| 35122 | Image* glyphImage = Image::get(promptBackImg->path.c_str()); | |||
| 35123 | if ( glyphImage ) | |||
| 35124 | { | |||
| 35125 | glyphPos.w = glyphImage->getWidth(); | |||
| 35126 | glyphPos.h = glyphImage->getHeight(); | |||
| 35127 | glyphPos.x -= glyphPos.w; | |||
| 35128 | glyphPos.x += 2; | |||
| 35129 | glyphPos.y += 2; | |||
| 35130 | promptBackImg->pos = glyphPos; | |||
| 35131 | } | |||
| 35132 | } | |||
| 35133 | if ( !promptGrab->isDisabled() ) | |||
| 35134 | { | |||
| 35135 | promptGrab->setText(Language::get(4091)); | |||
| 35136 | auto promptGrabImg = baseFrame->findImage("prompt grab img"); | |||
| 35137 | SDL_Rect glyphPos = promptGrabImg->pos; | |||
| 35138 | if ( auto textGet = Text::get(promptGrab->getText(), promptGrab->getFont(), | |||
| 35139 | promptGrab->getTextColor(), promptGrab->getOutlineColor()) ) | |||
| 35140 | { | |||
| 35141 | SDL_Rect textPos = promptGrab->getSize(); | |||
| 35142 | textPos.w = textGet->getWidth(); | |||
| 35143 | textPos.x = bg->pos.x + bg->pos.w - textPos.w - 8; | |||
| 35144 | textPos.y = promptBack->getSize().y - textPos.h + 2; | |||
| 35145 | promptGrab->setSize(textPos); | |||
| 35146 | glyphPos.x = promptGrab->getSize().x + promptGrab->getSize().w - textGet->getWidth() - 4; | |||
| 35147 | } | |||
| 35148 | promptGrabImg->path = Input::inputs[player.playernum].getGlyphPathForBinding("MenuPageRightAlt"); | |||
| 35149 | Image* glyphImage = Image::get(promptGrabImg->path.c_str()); | |||
| 35150 | if ( glyphImage ) | |||
| 35151 | { | |||
| 35152 | glyphPos.w = glyphImage->getWidth(); | |||
| 35153 | glyphPos.h = glyphImage->getHeight(); | |||
| 35154 | glyphPos.x -= glyphPos.w; | |||
| 35155 | furthestLeftPrompt = std::min(glyphPos.x + glyphPos.w / 2, furthestLeftPrompt); | |||
| 35156 | glyphPos.y = promptGrab->getSize().y + promptGrab->getSize().h / 2 - glyphPos.h / 2; | |||
| 35157 | promptGrabImg->pos = glyphPos; | |||
| 35158 | ||||
| 35159 | if ( furthestLeftPrompt < promptGrabImg->pos.x + promptGrabImg->pos.w / 2 ) | |||
| 35160 | { | |||
| 35161 | int offset = (promptGrabImg->pos.x + promptGrabImg->pos.w / 2) - furthestLeftPrompt; | |||
| 35162 | promptGrabImg->pos.x -= offset; | |||
| 35163 | auto pos = promptGrab->getSize(); | |||
| 35164 | pos.x -= offset; | |||
| 35165 | promptGrab->setSize(pos); | |||
| 35166 | } | |||
| 35167 | } | |||
| 35168 | } | |||
| 35169 | else if ( drawGlyphs ) | |||
| 35170 | { | |||
| 35171 | SDL_Rect glyphPos = grabAllBtn->getSize(); | |||
| 35172 | glyphPos.x += glyphPos.w / 2; | |||
| 35173 | glyphPos.y += glyphPos.h - 4; | |||
| 35174 | promptGrabImg->path = Input::inputs[player.playernum].getGlyphPathForBinding("MenuPageRightAlt"); | |||
| 35175 | promptGrabImg->ontop = true; | |||
| 35176 | Image* glyphImage = Image::get(promptGrabImg->path.c_str()); | |||
| 35177 | if ( glyphImage ) | |||
| 35178 | { | |||
| 35179 | glyphPos.w = glyphImage->getWidth(); | |||
| 35180 | glyphPos.h = glyphImage->getHeight(); | |||
| 35181 | glyphPos.x -= glyphPos.w / 2; | |||
| 35182 | promptGrabImg->pos = glyphPos; | |||
| 35183 | } | |||
| 35184 | } | |||
| 35185 | if ( !promptBack->isDisabled() ) | |||
| 35186 | { | |||
| 35187 | if ( furthestLeftPrompt < promptBackImg->pos.x + promptBackImg->pos.w / 2 ) | |||
| 35188 | { | |||
| 35189 | int offset = (promptBackImg->pos.x + promptBackImg->pos.w / 2) - furthestLeftPrompt; | |||
| 35190 | promptBackImg->pos.x -= offset; | |||
| 35191 | auto pos = promptBack->getSize(); | |||
| 35192 | pos.x = promptGrab->getSize().x; | |||
| 35193 | promptBack->setSize(pos); | |||
| 35194 | } | |||
| 35195 | } | |||
| 35196 | } | |||
| 35197 | ||||
| 35198 | bool closeChestAction = false; | |||
| 35199 | if ( !inputs.getUIInteraction(player.playernum)->selectedItem | |||
| 35200 | && player.GUI.bModuleAccessibleWithMouse(Player::GUI_t::MODULE_CHEST) | |||
| 35201 | && !player.GUI.isDropdownActive() | |||
| 35202 | && !player.inventoryUI.spellPanel.bOpen | |||
| 35203 | && player.bControlEnabled && !gamePaused && !player.usingCommand() ) | |||
| 35204 | { | |||
| 35205 | if ( openedChest[player.playernum] || bOpen ) | |||
| 35206 | { | |||
| 35207 | if ( Input::inputs[player.playernum].binaryToggle("MenuCancel") ) | |||
| 35208 | { | |||
| 35209 | Input::inputs[player.playernum].consumeBinaryToggle("MenuCancel"); | |||
| 35210 | closeChestAction = true; | |||
| 35211 | } | |||
| 35212 | else if ( !promptGrabImg->disabled && Input::inputs[player.playernum].consumeBinaryToggle("MenuPageRightAlt") ) | |||
| 35213 | { | |||
| 35214 | takeAllChestGUIAction(player.playernum); | |||
| 35215 | Player::soundActivate(); | |||
| 35216 | } | |||
| 35217 | } | |||
| 35218 | } | |||
| 35219 | ||||
| 35220 | SDL_Rect actualSize = chestSlotsFrame->getActualSize(); | |||
| 35221 | actualSize.y = scrollAnimateX; | |||
| 35222 | chestSlotsFrame->setActualSize(actualSize); | |||
| 35223 | ||||
| 35224 | if ( closeChestAction ) | |||
| 35225 | { | |||
| 35226 | closeChestGUIAction(player.playernum); | |||
| 35227 | return; | |||
| 35228 | } | |||
| 35229 | } | |||
| 35230 | ||||
| 35231 | bool Player::Inventory_t::ChestGUI_t::isSlotVisible(int x, int y) const | |||
| 35232 | { | |||
| 35233 | if ( player.inventoryUI.chestFrame ) | |||
| 35234 | { | |||
| 35235 | if ( player.inventoryUI.chestFrame->isDisabled() ) | |||
| 35236 | { | |||
| 35237 | return false; | |||
| 35238 | } | |||
| 35239 | } | |||
| 35240 | int lowerY = currentScrollRow; | |||
| 35241 | int upperY = currentScrollRow + getNumItemsToDisplayVertical() - 1; | |||
| 35242 | ||||
| 35243 | if ( y >= lowerY && y <= upperY ) | |||
| 35244 | { | |||
| 35245 | return true; | |||
| 35246 | } | |||
| 35247 | return false; | |||
| 35248 | } | |||
| 35249 | ||||
| 35250 | bool Player::Inventory_t::ChestGUI_t::isItemVisible(Item* item) const | |||
| 35251 | { | |||
| 35252 | if ( !item ) { return false; } | |||
| 35253 | return isSlotVisible(item->x, item->y); | |||
| 35254 | } | |||
| 35255 | ||||
| 35256 | void Player::Inventory_t::ChestGUI_t::scrollToSlot(int x, int y, bool instantly) | |||
| 35257 | { | |||
| 35258 | int lowerY = currentScrollRow; | |||
| 35259 | int upperY = currentScrollRow + getNumItemsToDisplayVertical() - 1; | |||
| 35260 | ||||
| 35261 | if ( y >= lowerY && y <= upperY ) | |||
| 35262 | { | |||
| 35263 | // no work to do. | |||
| 35264 | return; | |||
| 35265 | } | |||
| 35266 | ||||
| 35267 | int lowestItemY = getNumItemsToDisplayVertical() - 1; | |||
| 35268 | for ( node_t* node = stats[player.playernum]->inventory.first; node != NULL__null; node = node->next ) | |||
| 35269 | { | |||
| 35270 | Item* item = (Item*)node->element; | |||
| 35271 | if ( !item ) { continue; } | |||
| 35272 | if ( itemCategory(item) != SPELL_CAT ) { continue; } | |||
| 35273 | ||||
| 35274 | lowestItemY = std::max(lowestItemY, item->y); | |||
| 35275 | } | |||
| 35276 | int maxScroll = std::max((lowestItemY + 1) - (getNumItemsToDisplayVertical()), 0) * player.inventoryUI.getSlotSize(); | |||
| 35277 | ||||
| 35278 | int scrollAmount = 0; | |||
| 35279 | if ( y < lowerY ) | |||
| 35280 | { | |||
| 35281 | scrollAmount = (y)* player.inventoryUI.getSlotSize(); | |||
| 35282 | //scrollAmount += scrollSetpoint; | |||
| 35283 | } | |||
| 35284 | else if ( y > upperY ) | |||
| 35285 | { | |||
| 35286 | scrollAmount = (y - upperY) * player.inventoryUI.getSlotSize(); | |||
| 35287 | scrollAmount += scrollSetpoint; | |||
| 35288 | } | |||
| 35289 | scrollAmount = std::min(scrollAmount, maxScroll); | |||
| 35290 | ||||
| 35291 | scrollSetpoint = scrollAmount; | |||
| 35292 | if ( instantly ) | |||
| 35293 | { | |||
| 35294 | scrollAnimateX = scrollSetpoint; | |||
| 35295 | } | |||
| 35296 | currentScrollRow = scrollSetpoint / player.inventoryUI.getSlotSize(); | |||
| 35297 | if ( abs(scrollSetpoint - scrollAnimateX) > 0.00001 ) | |||
| 35298 | { | |||
| 35299 | isInteractable = false; | |||
| 35300 | } | |||
| 35301 | } | |||
| 35302 | ||||
| 35303 | void MinotaurWarning_t::deinit() | |||
| 35304 | { | |||
| 35305 | started = false; | |||
| 35306 | state = 0; | |||
| 35307 | stateInit = 0; | |||
| 35308 | animFade = 0.0; | |||
| 35309 | animTicks = 0; | |||
| 35310 | animBg = 0.0; | |||
| 35311 | initialWarningCompleted = false; | |||
| 35312 | minotaurSpawned = false; | |||
| 35313 | minotaurDied = false; | |||
| 35314 | minotaurUid = 0; | |||
| 35315 | animFlashIncrease = true; | |||
| 35316 | animFlash = 0.0; | |||
| 35317 | } | |||
| 35318 | ||||
| 35319 | void MinotaurWarning_t::init() | |||
| 35320 | { | |||
| 35321 | deinit(); | |||
| 35322 | started = true; | |||
| 35323 | } | |||
| 35324 | ||||
| 35325 | void MinotaurWarning_t::setAnimatePosition(const int destx, const int desty, const int destw, const int desth) | |||
| 35326 | { | |||
| 35327 | animateStartX = pos.x; | |||
| 35328 | animateStartY = pos.y; | |||
| 35329 | animateStartW = pos.w; | |||
| 35330 | animateStartH = pos.h; | |||
| 35331 | animateSetpointX = destx; | |||
| 35332 | animateSetpointY = desty; | |||
| 35333 | animateSetpointW = destw; | |||
| 35334 | animateSetpointH = desth; | |||
| 35335 | animateX = 0.0; | |||
| 35336 | animateY = 0.0; | |||
| 35337 | animateW = 0.0; | |||
| 35338 | animateH = 0.0; | |||
| 35339 | } | |||
| 35340 | ||||
| 35341 | void MinotaurWarning_t::setAnimatePosition(int destx, int desty) | |||
| 35342 | { | |||
| 35343 | animateStartX = pos.x; | |||
| 35344 | animateStartY = pos.y; | |||
| 35345 | animateStartW = pos.w; | |||
| 35346 | animateStartH = pos.h; | |||
| 35347 | animateSetpointX = destx; | |||
| 35348 | animateSetpointY = desty; | |||
| 35349 | animateSetpointW = 0; | |||
| 35350 | animateSetpointH = 0; | |||
| 35351 | animateX = 0.0; | |||
| 35352 | animateY = 0.0; | |||
| 35353 | animateW = 0.0; | |||
| 35354 | animateH = 0.0; | |||
| 35355 | } | |||
| 35356 | ||||
| 35357 | void Player::HUD_t::updateMinotaurWarning() | |||
| 35358 | { | |||
| 35359 | auto& m = minotaurWarning[player.playernum]; | |||
| 35360 | ||||
| 35361 | if ( gamePaused && multiplayer == SINGLE0 ) | |||
| 35362 | { | |||
| 35363 | if ( minotaurFrame ) | |||
| 35364 | { | |||
| 35365 | minotaurFrame->setDisabled(true); | |||
| 35366 | } | |||
| 35367 | return; | |||
| 35368 | } | |||
| 35369 | ||||
| 35370 | static ConsoleVariable<bool> cvar_minoanimdebug("/minoanimdebug", false); | |||
| 35371 | if ( *cvar_minoanimdebug && player.playernum == clientnum ) | |||
| 35372 | { | |||
| 35373 | *cvar_minoanimdebug = false; | |||
| 35374 | m.init(); | |||
| 35375 | } | |||
| 35376 | ||||
| 35377 | static ConsoleVariable<float> cvar_minoflashmax("/minoflashmax", 1.25); | |||
| 35378 | static ConsoleVariable<float> cvar_minoflashmin("/minoflashmin", 0.25); | |||
| 35379 | static ConsoleVariable<float> cvar_minoflashrate("/minoflashrate", 0.125); | |||
| 35380 | ||||
| 35381 | if ( m.processedOnTick == 0 ) | |||
| 35382 | { | |||
| 35383 | m.processedOnTick = ticks; | |||
| 35384 | } | |||
| 35385 | else if ( m.processedOnTick != ticks ) | |||
| 35386 | { | |||
| 35387 | m.processedOnTick = ticks; | |||
| 35388 | ++m.animTicks; | |||
| 35389 | } | |||
| 35390 | ||||
| 35391 | bool newLevel = m.levelProcessed != currentlevel; | |||
| 35392 | if ( !minotaurlevel || (newLevel && m.started) ) | |||
| 35393 | { | |||
| 35394 | m.deinit(); | |||
| 35395 | } | |||
| 35396 | m.levelProcessed = currentlevel; | |||
| 35397 | ||||
| 35398 | if ( !m.started ) | |||
| 35399 | { | |||
| 35400 | if ( minotaurFrame ) | |||
| 35401 | { | |||
| 35402 | minotaurFrame->setDisabled(true); | |||
| 35403 | } | |||
| 35404 | } | |||
| 35405 | if ( minotaurDisplay ) | |||
| 35406 | { | |||
| 35407 | minotaurDisplay->setDisabled(true); | |||
| 35408 | } | |||
| 35409 | if ( player.playernum == 0 && minotaurSharedDisplay ) | |||
| 35410 | { | |||
| 35411 | minotaurSharedDisplay->setDisabled(true); | |||
| 35412 | } | |||
| 35413 | ||||
| 35414 | if ( !player.isLocalPlayer() ) | |||
| 35415 | { | |||
| 35416 | m.deinit(); | |||
| 35417 | return; | |||
| 35418 | } | |||
| 35419 | ||||
| 35420 | if ( minotaurlevel && m.animTicks >= 50 && !m.started ) | |||
| 35421 | { | |||
| 35422 | m.init(); | |||
| 35423 | } | |||
| 35424 | ||||
| 35425 | if ( !m.started ) | |||
| 35426 | { | |||
| 35427 | return; | |||
| 35428 | } | |||
| 35429 | ||||
| 35430 | if ( !minotaurFrame ) | |||
| 35431 | { | |||
| 35432 | minotaurFrame = gameUIFrame[player.playernum]->addFrame("minotaur"); | |||
| 35433 | minotaurFrame->setInheritParentFrameOpacity(false); | |||
| 35434 | minotaurFrame->setHollow(true); | |||
| 35435 | ||||
| 35436 | Frame::image_t* img = minotaurFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0, | |||
| 35437 | "*images/system/white.png", "mino dimmer"); | |||
| 35438 | img->disabled = true; | |||
| 35439 | ||||
| 35440 | img = minotaurFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, | |||
| 35441 | "*images/ui/HUD/HUD_Minotaur_00.png", "mino img bg"); | |||
| 35442 | img->disabled = true; | |||
| 35443 | ||||
| 35444 | img = minotaurFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, | |||
| 35445 | "*images/ui/HUD/HUD_Minotaur_00.png", "mino img fg"); | |||
| 35446 | img->disabled = true; | |||
| 35447 | } | |||
| 35448 | ||||
| 35449 | minotaurFrame->setSize(SDL_Rect{ | |||
| 35450 | player.camera_virtualx1(), | |||
| 35451 | player.camera_virtualy1(), | |||
| 35452 | player.camera_virtualWidth(), | |||
| 35453 | player.camera_virtualHeight() }); | |||
| 35454 | ||||
| 35455 | auto dimmer = minotaurFrame->findImage("mino dimmer"); | |||
| 35456 | dimmer->pos = SDL_Rect{ 0, 0, minotaurFrame->getSize().w, minotaurFrame->getSize().h }; | |||
| 35457 | dimmer->disabled = false; | |||
| 35458 | auto minotaurImgBg = minotaurFrame->findImage("mino img bg"); | |||
| 35459 | minotaurImgBg->disabled = true; | |||
| 35460 | auto minotaurImgFg = minotaurFrame->findImage("mino img fg"); | |||
| 35461 | minotaurImgFg->disabled = true; | |||
| 35462 | minotaurFrame->setDisabled(player.hud.hudFrame->isDisabled()); | |||
| 35463 | int imgSizeX = 60; | |||
| 35464 | int imgSizeY = 66; | |||
| 35465 | if ( auto imgGet = Image::get(minotaurImgBg->path.c_str()) ) | |||
| 35466 | { | |||
| 35467 | imgSizeX = imgGet->getWidth(); | |||
| 35468 | imgSizeY = imgGet->getHeight(); | |||
| 35469 | } | |||
| 35470 | const int midX = dimmer->pos.w / 2; | |||
| 35471 | const int midY = dimmer->pos.h / 2; | |||
| 35472 | ||||
| 35473 | std::string minimapFrameName = "minimap"; | |||
| 35474 | minimapFrameName.append(std::to_string(player.playernum)); | |||
| 35475 | SDL_Rect sharedminimapPos{ 0, 0, 0, 0 }; | |||
| 35476 | SDL_Rect minimapPos{ 0, 0, 0, 0 }; | |||
| 35477 | Frame* minimap = nullptr; | |||
| 35478 | bool leftAlignToMap = splitscreen | |||
| 35479 | && player.bUseCompactGUIHeight() | |||
| 35480 | && !player.bUseCompactGUIWidth(); | |||
| 35481 | int leftAlignYOffset = 16; | |||
| 35482 | int leftAlignXOffset = 0; | |||
| 35483 | int topAlignYOffset = 0; | |||
| 35484 | if ( leftAlignToMap && *MainMenu::clipped_splitscreen && player.hud.actionPromptsFrame && !player.hud.actionPromptsFrame->isDisabled() ) | |||
| 35485 | { | |||
| 35486 | leftAlignYOffset += 16; | |||
| 35487 | leftAlignXOffset += 8; | |||
| 35488 | } | |||
| 35489 | else if ( !leftAlignToMap && *MainMenu::clipped_splitscreen && !player.bUseCompactGUIHeight() && player.bUseCompactGUIWidth() ) | |||
| 35490 | { | |||
| 35491 | topAlignYOffset = -8; | |||
| 35492 | } | |||
| 35493 | if ( minimap = player.hud.hudFrame->findFrame(minimapFrameName.c_str()) ) | |||
| 35494 | { | |||
| 35495 | minimapPos.x = minotaurFrame->getSize().w - player.minimap.minimapPos.w; | |||
| 35496 | minimapPos.y = minotaurFrame->getSize().h - player.minimap.minimapPos.h; | |||
| 35497 | int mapHeightOffset = 0; | |||
| 35498 | if ( player.hud.mapPromptFrame && !player.hud.mapPromptFrame->isDisabled() ) | |||
| 35499 | { | |||
| 35500 | mapHeightOffset = player.hud.mapPromptFrame->getSize().h; | |||
| 35501 | } | |||
| 35502 | else if ( player.hud.gameTimerFrame && !player.hud.gameTimerFrame->isDisabled() | |||
| 35503 | // ignore if ui raised above hotbar and vertical split layout | |||
| 35504 | && (!(player.hud.offsetHUDAboveHotbarHeight > 0 && splitscreen && !player.bUseCompactGUIHeight() && player.bUseCompactGUIWidth())) ) | |||
| 35505 | { | |||
| 35506 | mapHeightOffset = player.hud.gameTimerFrame->getSize().h; | |||
| 35507 | } | |||
| 35508 | else if ( player.hud.actionPromptsFrame && !player.hud.actionPromptsFrame->isDisabled() ) | |||
| 35509 | { | |||
| 35510 | leftAlignYOffset += 44; | |||
| 35511 | } | |||
| 35512 | mapHeightOffset += player.hud.offsetHUDAboveHotbarHeight; | |||
| 35513 | minimapPos.y -= mapHeightOffset; | |||
| 35514 | } | |||
| 35515 | minimapPos.w = player.minimap.minimapPos.w; | |||
| 35516 | minimapPos.h = player.minimap.minimapPos.h; | |||
| 35517 | if ( ::minimapFrame ) | |||
| 35518 | { | |||
| 35519 | sharedminimapPos = Player::Minimap_t::sharedMinimapPos; | |||
| 35520 | } | |||
| 35521 | ||||
| 35522 | { | |||
| 35523 | Uint8 r, g, b, a; | |||
| 35524 | getColor(dimmer->color, &r, &g, &b, &a); | |||
| 35525 | a = m.animFade * 64; | |||
| 35526 | dimmer->color = makeColor(r, g, b, a); | |||
| 35527 | ||||
| 35528 | if ( m.state >= 8 || m.initialWarningCompleted ) | |||
| 35529 | { | |||
| 35530 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 35531 | real_t setpointDiff = fpsScale * std::max(.01, (m.animFade)) / 5.0; | |||
| 35532 | m.animFade -= setpointDiff; | |||
| 35533 | m.animFade = std::max(0.0, m.animFade); | |||
| 35534 | } | |||
| 35535 | else | |||
| 35536 | { | |||
| 35537 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 35538 | real_t setpointDiff = fpsScale * std::max(.01, (1.0 - m.animFade)) / 5.0; | |||
| 35539 | m.animFade += setpointDiff; | |||
| 35540 | m.animFade = std::min(1.0, m.animFade); | |||
| 35541 | } | |||
| 35542 | } | |||
| 35543 | ||||
| 35544 | static ConsoleVariable<float> cvar_minoanimspeed("/minoanimspeed", 1.0); | |||
| 35545 | static ConsoleVariable<int> cvar_minoanimvolume("/minoanimvolume", 128); | |||
| 35546 | real_t animspeed = 5.0 * (*cvar_minoanimspeed);//5.0 / 4.0; | |||
| 35547 | const int movementAmount = 0; | |||
| 35548 | real_t scalingAmount = 2.0; | |||
| 35549 | real_t midScalingAmount = 1.5; | |||
| 35550 | ||||
| 35551 | if ( m.state == 0 ) | |||
| 35552 | { | |||
| 35553 | if ( m.stateInit == 0 ) | |||
| 35554 | { | |||
| 35555 | m.pos = SDL_Rect{ midX - imgSizeX / 2, midY - imgSizeY / 2, imgSizeX, imgSizeY }; | |||
| 35556 | m.stateInit = 1; | |||
| 35557 | m.setAnimatePosition( | |||
| 35558 | midX - imgSizeX / 2 - movementAmount, | |||
| 35559 | midY - imgSizeY / 2 - movementAmount, | |||
| 35560 | imgSizeX, imgSizeY); | |||
| 35561 | } | |||
| 35562 | minotaurImgFg->color = makeColor(255, 255, 255, 255 * m.animateX); | |||
| 35563 | minotaurImgFg->disabled = false; | |||
| 35564 | if ( m.animateX >= 1.0 ) | |||
| 35565 | { | |||
| 35566 | m.animTicks = 0; | |||
| 35567 | m.state = 1; | |||
| 35568 | } | |||
| 35569 | animspeed *= 2; | |||
| 35570 | } | |||
| 35571 | else if ( m.state == 1 ) | |||
| 35572 | { | |||
| 35573 | if ( m.stateInit == 1 ) | |||
| 35574 | { | |||
| 35575 | m.stateInit = 2; | |||
| 35576 | m.setAnimatePosition( | |||
| 35577 | midX - imgSizeX / 2 - movementAmount - (scalingAmount - 1.0) * imgSizeX / 2, | |||
| 35578 | midY - imgSizeY / 2 - movementAmount - (scalingAmount - 1.0) * imgSizeY / 2, | |||
| 35579 | imgSizeX * scalingAmount, | |||
| 35580 | imgSizeY * scalingAmount); | |||
| 35581 | } | |||
| 35582 | minotaurImgFg->color = 0xFFFFFFFF; | |||
| 35583 | minotaurImgFg->disabled = false; | |||
| 35584 | if ( m.animateX >= 1.0 ) | |||
| 35585 | { | |||
| 35586 | m.animTicks = 0; | |||
| 35587 | m.state = 2; | |||
| 35588 | } | |||
| 35589 | animspeed /= 2; | |||
| 35590 | } | |||
| 35591 | else if ( m.state == 2 ) | |||
| 35592 | { | |||
| 35593 | if ( m.stateInit == 2 ) | |||
| 35594 | { | |||
| 35595 | m.stateInit = 3; | |||
| 35596 | m.setAnimatePosition( | |||
| 35597 | midX - imgSizeX / 2 - movementAmount - (midScalingAmount - 1.0) * imgSizeX / 2, | |||
| 35598 | midY - imgSizeY / 2 - movementAmount - (midScalingAmount - 1.0) * imgSizeY / 2, | |||
| 35599 | imgSizeX * midScalingAmount, | |||
| 35600 | imgSizeY * midScalingAmount); | |||
| 35601 | m.animBg = 1.0; | |||
| 35602 | if ( !splitscreen || (splitscreen && player.playernum == 0) ) | |||
| 35603 | { | |||
| 35604 | playSound(514, *cvar_minoanimvolume); | |||
| 35605 | } | |||
| 35606 | } | |||
| 35607 | minotaurImgFg->disabled = false; | |||
| 35608 | ||||
| 35609 | minotaurImgBg->pos = SDL_Rect{ midX - imgSizeX, | |||
| 35610 | midY - imgSizeY, imgSizeX * 2, imgSizeY * 2 }; | |||
| 35611 | if ( m.animateX >= 1.0 ) | |||
| 35612 | { | |||
| 35613 | m.animTicks = 0; | |||
| 35614 | m.state = 3; | |||
| 35615 | } | |||
| 35616 | } | |||
| 35617 | else if ( m.state == 3 ) | |||
| 35618 | { | |||
| 35619 | if ( m.stateInit == 3 ) | |||
| 35620 | { | |||
| 35621 | m.stateInit = 4; | |||
| 35622 | m.setAnimatePosition( | |||
| 35623 | midX - imgSizeX / 2 - movementAmount - (midScalingAmount - 1.0) * imgSizeX / 2, | |||
| 35624 | midY - imgSizeY / 2 - movementAmount - (midScalingAmount - 1.0) * imgSizeY / 2, | |||
| 35625 | imgSizeX * midScalingAmount, | |||
| 35626 | imgSizeY * midScalingAmount); | |||
| 35627 | } | |||
| 35628 | minotaurImgFg->disabled = false; | |||
| 35629 | ||||
| 35630 | if ( m.animateX >= 1.0 ) | |||
| 35631 | { | |||
| 35632 | m.animTicks = 0; | |||
| 35633 | m.state = 4; | |||
| 35634 | } | |||
| 35635 | } | |||
| 35636 | else if ( m.state == 4 ) | |||
| 35637 | { | |||
| 35638 | if ( m.stateInit == 4 ) | |||
| 35639 | { | |||
| 35640 | m.stateInit = 5; | |||
| 35641 | m.setAnimatePosition( | |||
| 35642 | midX - imgSizeX / 2 - movementAmount, | |||
| 35643 | midY - imgSizeY / 2 - movementAmount, | |||
| 35644 | imgSizeX, imgSizeY); | |||
| 35645 | } | |||
| 35646 | minotaurImgFg->disabled = false; | |||
| 35647 | ||||
| 35648 | if ( m.animateX >= 1.0 ) | |||
| 35649 | { | |||
| 35650 | m.animTicks = 0; | |||
| 35651 | m.state = 5; | |||
| 35652 | } | |||
| 35653 | animspeed /= 2; | |||
| 35654 | } | |||
| 35655 | else if ( m.state == 5 ) | |||
| 35656 | { | |||
| 35657 | if ( m.stateInit == 5 ) | |||
| 35658 | { | |||
| 35659 | m.stateInit = 6; | |||
| 35660 | m.setAnimatePosition( | |||
| 35661 | midX - imgSizeX / 2 - movementAmount - (scalingAmount - 1.0) * imgSizeX / 2, | |||
| 35662 | midY - imgSizeY / 2 - movementAmount - (scalingAmount - 1.0) * imgSizeY / 2, | |||
| 35663 | imgSizeX * scalingAmount, | |||
| 35664 | imgSizeY * scalingAmount); | |||
| 35665 | } | |||
| 35666 | minotaurImgFg->color = 0xFFFFFFFF; | |||
| 35667 | minotaurImgFg->disabled = false; | |||
| 35668 | if ( m.animateX >= 1.0 ) | |||
| 35669 | { | |||
| 35670 | m.animTicks = 0; | |||
| 35671 | m.state = 6; | |||
| 35672 | } | |||
| 35673 | animspeed /= 2; | |||
| 35674 | } | |||
| 35675 | else if ( m.state == 6 ) | |||
| 35676 | { | |||
| 35677 | if ( m.stateInit == 6 ) | |||
| 35678 | { | |||
| 35679 | m.stateInit = 7; | |||
| 35680 | m.setAnimatePosition( | |||
| 35681 | midX - imgSizeX / 2 - movementAmount - (midScalingAmount - 1.0) * imgSizeX / 2, | |||
| 35682 | midY - imgSizeY / 2 - movementAmount - (midScalingAmount - 1.0) * imgSizeY / 2, | |||
| 35683 | imgSizeX * midScalingAmount, | |||
| 35684 | imgSizeY * midScalingAmount); | |||
| 35685 | m.animBg = 1.0; | |||
| 35686 | if ( !splitscreen || (splitscreen && player.playernum == 0) ) | |||
| 35687 | { | |||
| 35688 | playSound(515, *cvar_minoanimvolume); | |||
| 35689 | } | |||
| 35690 | } | |||
| 35691 | minotaurImgFg->disabled = false; | |||
| 35692 | ||||
| 35693 | if ( m.animateX >= 1.0 ) | |||
| 35694 | { | |||
| 35695 | m.animTicks = 0; | |||
| 35696 | m.state = 7; | |||
| 35697 | } | |||
| 35698 | } | |||
| 35699 | else if ( m.state == 7 ) | |||
| 35700 | { | |||
| 35701 | if ( m.stateInit == 7 ) | |||
| 35702 | { | |||
| 35703 | m.stateInit = 8; | |||
| 35704 | m.setAnimatePosition( | |||
| 35705 | midX - imgSizeX / 2 - movementAmount - (midScalingAmount - 1.0) * imgSizeX / 2, | |||
| 35706 | midY - imgSizeY / 2 - movementAmount - (midScalingAmount - 1.0) * imgSizeY / 2, | |||
| 35707 | imgSizeX * midScalingAmount, | |||
| 35708 | imgSizeY * midScalingAmount); | |||
| 35709 | } | |||
| 35710 | minotaurImgFg->disabled = false; | |||
| 35711 | ||||
| 35712 | if ( m.animateX >= 1.0 ) | |||
| 35713 | { | |||
| 35714 | m.animTicks = 0; | |||
| 35715 | m.state = 8; | |||
| 35716 | } | |||
| 35717 | } | |||
| 35718 | else if ( m.state == 8 ) | |||
| 35719 | { | |||
| 35720 | if ( m.stateInit == 8 ) | |||
| 35721 | { | |||
| 35722 | m.stateInit = 9; | |||
| 35723 | m.setAnimatePosition( | |||
| 35724 | midX - imgSizeX / 2 - movementAmount, | |||
| 35725 | midY - imgSizeY / 2 - movementAmount, | |||
| 35726 | imgSizeX, imgSizeY); | |||
| 35727 | } | |||
| 35728 | minotaurImgFg->color = makeColor(255, 255, 255, 255); | |||
| 35729 | minotaurImgFg->disabled = false; | |||
| 35730 | ||||
| 35731 | if ( m.animateX >= 1.0 ) | |||
| 35732 | { | |||
| 35733 | m.animTicks = 0; | |||
| 35734 | m.state = 9; | |||
| 35735 | } | |||
| 35736 | animspeed /= 2; | |||
| 35737 | } | |||
| 35738 | else if ( m.state == 9 ) | |||
| 35739 | { | |||
| 35740 | if ( m.stateInit == 9 ) | |||
| 35741 | { | |||
| 35742 | m.stateInit = 10; | |||
| 35743 | if ( ::minimapFrame && !::minimapFrame->isInvisible() && sharedminimapPos.x > 0 ) | |||
| 35744 | { | |||
| 35745 | if ( minotaurSharedDisplay ) | |||
| 35746 | { | |||
| 35747 | /*m.setAnimatePosition( | |||
| 35748 | sharedminimapPos.x + sharedminimapPos.w / 2 - imgSizeX / 2 - movementAmount, | |||
| 35749 | sharedminimapPos.y - imgSizeY - 16 - movementAmount, | |||
| 35750 | imgSizeX, imgSizeY);*/ | |||
| 35751 | } | |||
| 35752 | m.setAnimatePosition( | |||
| 35753 | midX - imgSizeX / 2 - movementAmount, | |||
| 35754 | midY - imgSizeY / 2 - movementAmount, | |||
| 35755 | imgSizeX, imgSizeY); | |||
| 35756 | } | |||
| 35757 | else if ( minotaurDisplay && minimap && !minimap->isInvisible() && minimapPos.x > 0 ) | |||
| 35758 | { | |||
| 35759 | if ( leftAlignToMap ) | |||
| 35760 | { | |||
| 35761 | m.setAnimatePosition( | |||
| 35762 | minimapPos.x - imgSizeX - 16 + leftAlignXOffset - movementAmount, | |||
| 35763 | minimapPos.y + minimapPos.h - imgSizeY - leftAlignYOffset - movementAmount, | |||
| 35764 | imgSizeX, imgSizeY); | |||
| 35765 | } | |||
| 35766 | else | |||
| 35767 | { | |||
| 35768 | m.setAnimatePosition( | |||
| 35769 | minimapPos.x + minimapPos.w - imgSizeX - 16 - movementAmount, | |||
| 35770 | minimapPos.y - imgSizeY - 16 - topAlignYOffset - movementAmount, | |||
| 35771 | imgSizeX, imgSizeY); | |||
| 35772 | } | |||
| 35773 | } | |||
| 35774 | else | |||
| 35775 | { | |||
| 35776 | m.setAnimatePosition( | |||
| 35777 | minotaurFrame->getSize().w - imgSizeX - 16 - movementAmount, | |||
| 35778 | minotaurFrame->getSize().h - imgSizeY - 16 - movementAmount, | |||
| 35779 | imgSizeX, imgSizeY); | |||
| 35780 | } | |||
| 35781 | } | |||
| 35782 | ||||
| 35783 | minotaurImgFg->color = makeColor(255, 255, 255, 255); | |||
| 35784 | if ( ::minimapFrame && !::minimapFrame->isInvisible() ) | |||
| 35785 | { | |||
| 35786 | /*if ( !minotaurSharedDisplay )*/ | |||
| 35787 | { | |||
| 35788 | // fade out icon for local splitscreen | |||
| 35789 | minotaurImgFg->color = makeColor(255, 255, 255, 255 * (1.0 - m.animateX)); | |||
| 35790 | } | |||
| 35791 | } | |||
| 35792 | ||||
| 35793 | minotaurImgFg->disabled = false; | |||
| 35794 | ||||
| 35795 | if ( m.animateX >= 1.0 ) | |||
| 35796 | { | |||
| 35797 | m.animTicks = 0; | |||
| 35798 | m.state = 10; | |||
| 35799 | m.animFlash = *cvar_minoflashmax * 2; | |||
| 35800 | m.animFlashIncrease = false; | |||
| 35801 | /*if ( !splitscreen || (splitscreen && player.playernum == 0) ) | |||
| 35802 | { | |||
| 35803 | playSound(517, 64); | |||
| 35804 | }*/ | |||
| 35805 | } | |||
| 35806 | } | |||
| 35807 | else if ( m.state == 10 ) | |||
| 35808 | { | |||
| 35809 | m.initialWarningCompleted = true; | |||
| 35810 | } | |||
| 35811 | ||||
| 35812 | if ( m.initialWarningCompleted ) | |||
| 35813 | { | |||
| 35814 | if ( !m.minotaurDied && ticks % 5 == 0 && (!splitscreen || splitscreen && player.playernum == 0) ) | |||
| 35815 | { | |||
| 35816 | if ( !m.minotaurSpawned ) | |||
| 35817 | { | |||
| 35818 | for ( node_t* mapNode = map.creatures->first; mapNode != nullptr; mapNode = mapNode->next ) | |||
| 35819 | { | |||
| 35820 | Entity* monster = (Entity*)mapNode->element; | |||
| 35821 | if ( monster && monster->getMonsterTypeFromSprite() == MINOTAUR ) | |||
| 35822 | { | |||
| 35823 | m.minotaurSpawned = true; | |||
| 35824 | m.minotaurUid = monster->getUID(); | |||
| 35825 | } | |||
| 35826 | } | |||
| 35827 | } | |||
| 35828 | else if ( !uidToEntity(m.minotaurUid) ) | |||
| 35829 | { | |||
| 35830 | m.minotaurDied = true; | |||
| 35831 | } | |||
| 35832 | } | |||
| 35833 | ||||
| 35834 | if ( splitscreen && player.playernum != 0 ) | |||
| 35835 | { | |||
| 35836 | m.minotaurDied = minotaurWarning[0].minotaurDied; | |||
| 35837 | m.minotaurSpawned = minotaurWarning[0].minotaurSpawned; | |||
| 35838 | } | |||
| 35839 | ||||
| 35840 | bool flash = false; | |||
| 35841 | if ( m.minotaurSpawned && !m.minotaurDied ) | |||
| 35842 | { | |||
| 35843 | m.animFlash = 1.0; | |||
| 35844 | flash = !((ticks % 50) - (ticks % 25)); | |||
| 35845 | } | |||
| 35846 | else if ( m.animFlashIncrease ) | |||
| 35847 | { | |||
| 35848 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 35849 | real_t setpointDiff = fpsScale * (*cvar_minoflashrate) / 5.0; | |||
| 35850 | m.animFlash += setpointDiff; | |||
| 35851 | if ( m.animFlash >= *cvar_minoflashmax ) | |||
| 35852 | { | |||
| 35853 | m.animFlashIncrease = false; | |||
| 35854 | } | |||
| 35855 | m.animFlash = std::min(*cvar_minoflashmax, (float)m.animFlash); | |||
| 35856 | } | |||
| 35857 | else | |||
| 35858 | { | |||
| 35859 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 35860 | real_t setpointDiff = fpsScale * (*cvar_minoflashrate) / 5.0; | |||
| 35861 | m.animFlash -= setpointDiff; | |||
| 35862 | if ( m.animFlash <= *cvar_minoflashmin ) | |||
| 35863 | { | |||
| 35864 | m.animFlashIncrease = true; | |||
| 35865 | } | |||
| 35866 | m.animFlash = std::max(*cvar_minoflashmin, (float)m.animFlash); | |||
| 35867 | } | |||
| 35868 | ||||
| 35869 | if ( m.minotaurDied ) | |||
| 35870 | { | |||
| 35871 | // don't show icon. | |||
| 35872 | } | |||
| 35873 | else if ( ::minimapFrame && !::minimapFrame->isInvisible() && sharedminimapPos.x > 0 ) | |||
| 35874 | { | |||
| 35875 | if ( minotaurSharedDisplay ) | |||
| 35876 | { | |||
| 35877 | minotaurSharedDisplay->setDisabled(flash); | |||
| 35878 | minotaurSharedDisplay->setOpacity(100.0 * std::max(0.25, std::min(1.0, m.animFlash))); | |||
| 35879 | minotaurSharedDisplay->setSize(SDL_Rect{ sharedminimapPos.x + sharedminimapPos.w / 2 - imgSizeX / 2 - movementAmount, | |||
| 35880 | sharedminimapPos.y - imgSizeY - 16 - movementAmount, | |||
| 35881 | imgSizeX, imgSizeY }); | |||
| 35882 | /*if ( (minotaurSharedDisplay->getSize().x + minotaurSharedDisplay->getSize().w) > | |||
| 35883 | (players[0]->camera_virtualx1() + players[0]->camera_virtualWidth()) )*/ | |||
| 35884 | { | |||
| 35885 | // keep on player 1's camera for now. | |||
| 35886 | SDL_Rect pos = minotaurSharedDisplay->getSize(); | |||
| 35887 | //int diff = (players[0]->camera_virtualx1() + players[0]->camera_virtualWidth()) - | |||
| 35888 | // (minotaurSharedDisplay->getSize().x + minotaurSharedDisplay->getSize().w); | |||
| 35889 | //pos.x -= abs(diff) + 4; | |||
| 35890 | pos.x = players[0]->camera_virtualx1() + players[0]->camera_virtualWidth() - pos.w - 4; | |||
| 35891 | pos.y = players[0]->camera_virtualy1() + players[0]->camera_virtualHeight() - pos.h - 4; | |||
| 35892 | if ( players[0]->hud.mapPromptFrame && !players[0]->hud.mapPromptFrame->isDisabled() ) | |||
| 35893 | { | |||
| 35894 | pos.y -= players[0]->hud.mapPromptFrame->getSize().h; | |||
| 35895 | } | |||
| 35896 | minotaurSharedDisplay->setSize(pos); | |||
| 35897 | } | |||
| 35898 | } | |||
| 35899 | } | |||
| 35900 | else if ( minotaurDisplay && minimap && !minimap->isInvisible() && minimapPos.x > 0 ) | |||
| 35901 | { | |||
| 35902 | minotaurDisplay->setDisabled(flash); | |||
| 35903 | minotaurDisplay->setOpacity(100.0 * std::max(0.25, std::min(1.0, m.animFlash))); | |||
| 35904 | ||||
| 35905 | if ( leftAlignToMap ) | |||
| 35906 | { | |||
| 35907 | minotaurDisplay->setSize(SDL_Rect{ | |||
| 35908 | minimapPos.x - imgSizeX - 16 + leftAlignXOffset - movementAmount, | |||
| 35909 | minimapPos.y + minimapPos.h - imgSizeY - leftAlignYOffset - movementAmount, | |||
| 35910 | imgSizeX, imgSizeY }); | |||
| 35911 | } | |||
| 35912 | else | |||
| 35913 | { | |||
| 35914 | minotaurDisplay->setSize(SDL_Rect{ minimapPos.x + minimapPos.w - imgSizeX - 16 - movementAmount, | |||
| 35915 | minimapPos.y - imgSizeY - 16 - topAlignYOffset - movementAmount, | |||
| 35916 | imgSizeX, imgSizeY }); | |||
| 35917 | } | |||
| 35918 | } | |||
| 35919 | else | |||
| 35920 | { | |||
| 35921 | minotaurDisplay->setDisabled(flash); | |||
| 35922 | minotaurDisplay->setOpacity(100.0 * std::max(0.25, std::min(1.0, m.animFlash))); | |||
| 35923 | minotaurDisplay->setSize(SDL_Rect{ minotaurFrame->getSize().w - imgSizeX - 16 - movementAmount, | |||
| 35924 | minotaurFrame->getSize().h - imgSizeY - 16 - movementAmount, | |||
| 35925 | imgSizeX, imgSizeY }); | |||
| 35926 | } | |||
| 35927 | } | |||
| 35928 | ||||
| 35929 | if ( m.animBg > 0.0 ) | |||
| 35930 | { | |||
| 35931 | minotaurImgBg->color = makeColor(255, 255, 255, 255 * (std::min(1.0, m.animBg))); | |||
| 35932 | minotaurImgBg->disabled = false; | |||
| 35933 | } | |||
| 35934 | ||||
| 35935 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 35936 | real_t setpointDiffX = fpsScale * std::max(.1, (1.0 - m.animateX)) / (animspeed); | |||
| 35937 | real_t setpointDiffY = fpsScale * std::max(.1, (1.0 - m.animateY)) / (animspeed); | |||
| 35938 | real_t setpointDiffW = fpsScale * std::max(.1, (1.0 - m.animateW)) / (animspeed); | |||
| 35939 | real_t setpointDiffH = fpsScale * std::max(.1, (1.0 - m.animateH)) / (animspeed); | |||
| 35940 | m.animateX += setpointDiffX; | |||
| 35941 | m.animateY += setpointDiffY; | |||
| 35942 | m.animateX = std::min(1.0, m.animateX); | |||
| 35943 | m.animateY = std::min(1.0, m.animateY); | |||
| 35944 | m.animateW += setpointDiffW; | |||
| 35945 | m.animateH += setpointDiffH; | |||
| 35946 | m.animateW = std::min(1.0, m.animateW); | |||
| 35947 | m.animateH = std::min(1.0, m.animateH); | |||
| 35948 | ||||
| 35949 | int destX = m.animateSetpointX - m.animateStartX; | |||
| 35950 | int destY = m.animateSetpointY - m.animateStartY; | |||
| 35951 | int destW = m.animateSetpointW - m.animateStartW; | |||
| 35952 | int destH = m.animateSetpointH - m.animateStartH; | |||
| 35953 | ||||
| 35954 | m.pos.x = m.animateStartX + destX * m.animateX; | |||
| 35955 | m.pos.y = m.animateStartY + destY * m.animateY; | |||
| 35956 | m.pos.w = m.animateStartW + destW * m.animateW; | |||
| 35957 | m.pos.h = m.animateStartH + destH * m.animateH; | |||
| 35958 | minotaurImgFg->pos = m.pos; | |||
| 35959 | ||||
| 35960 | m.animBg -= fpsScale * 0.2 / animspeed; | |||
| 35961 | m.animBg = std::max(0.0, m.animBg); | |||
| 35962 | } | |||
| 35963 | ||||
| 35964 | bool Player::WorldUI_t::WorldTooltipItem_t::isItemSameAsCurrent(Item* item) | |||
| 35965 | { | |||
| 35966 | if ( !item ) | |||
| 35967 | { | |||
| 35968 | return false; | |||
| 35969 | } | |||
| 35970 | if ( item->type == type | |||
| 35971 | && item->status == status | |||
| 35972 | && item->beatitude == beatitude | |||
| 35973 | && item->count == count | |||
| 35974 | && item->appearance == appearance | |||
| 35975 | && item->identified == identified ) | |||
| 35976 | { | |||
| 35977 | return true; | |||
| 35978 | } | |||
| 35979 | return false; | |||
| 35980 | } | |||
| 35981 | ||||
| 35982 | ||||
| 35983 | SDL_Surface* Player::WorldUI_t::WorldTooltipItem_t::blitItemWorldTooltip(Item* item) | |||
| 35984 | { | |||
| 35985 | if ( !item ) | |||
| 35986 | { | |||
| 35987 | return nullptr; | |||
| 35988 | } | |||
| 35989 | ||||
| 35990 | if ( itemWorldTooltipSurface && isItemSameAsCurrent(item) ) | |||
| 35991 | { | |||
| 35992 | return itemWorldTooltipSurface; | |||
| 35993 | } | |||
| 35994 | ||||
| 35995 | type = item->type; | |||
| 35996 | status = item->status; | |||
| 35997 | beatitude = item->beatitude; | |||
| 35998 | count = item->count; | |||
| 35999 | appearance = item->appearance; | |||
| 36000 | identified = item->identified; | |||
| 36001 | ||||
| 36002 | SDL_Rect tooltip; | |||
| 36003 | char buf[1024] = ""; | |||
| 36004 | char buf2[1024] = ""; | |||
| 36005 | int numHeaderLines = 1; | |||
| 36006 | int numDescLines = 3; | |||
| 36007 | Font* font = Font::get("fonts/pixel_maz.ttf#32#2"); | |||
| 36008 | int headerSize = 16; | |||
| 36009 | ||||
| 36010 | if ( !itemFrame ) | |||
| 36011 | { | |||
| 36012 | itemFrame = new Frame("world tooltip frame"); | |||
| 36013 | itemFrame->setSize(SDL_Rect{ 0, 0, player.hotbar.getSlotSize() - 4, player.hotbar.getSlotSize() - 4 }); | |||
| 36014 | itemFrame->setUserData(&GAMEUI_FRAMEDATA_WORLDTOOLTIP_ITEM); | |||
| 36015 | createPlayerInventorySlotFrameElements(itemFrame); | |||
| 36016 | itemFrame->setSize(SDL_Rect{ 0, 0, player.hotbar.getSlotSize(), player.hotbar.getSlotSize() }); | |||
| 36017 | } | |||
| 36018 | ||||
| 36019 | updateSlotFrameFromItem(itemFrame, item); | |||
| 36020 | ||||
| 36021 | // get tooltip name and background | |||
| 36022 | { | |||
| 36023 | if ( !item->identified ) | |||
| 36024 | { | |||
| 36025 | if ( itemCategory(item) == BOOK ) | |||
| 36026 | { | |||
| 36027 | snprintf(buf, sizeof(buf), "%s %s", ItemTooltips.getItemStatusAdjective(item->type, item->status).c_str(), | |||
| 36028 | Language::get(4214)); // brand new copy of | |||
| 36029 | snprintf(buf2, sizeof(buf), "%s (?)", getBookLocalizedNameFromIndex(item->appearance % numbooks).c_str()); | |||
| 36030 | } | |||
| 36031 | else if ( itemCategory(item) == SCROLL ) | |||
| 36032 | { | |||
| 36033 | snprintf(buf, sizeof(buf), "%s %s", ItemTooltips.getItemStatusAdjective(item->type, item->status).c_str(), | |||
| 36034 | items[item->type].getUnidentifiedName()); | |||
| 36035 | snprintf(buf2, sizeof(buf), "%s %s (?)", Language::get(4215), item->getScrollLabel()); | |||
| 36036 | } | |||
| 36037 | else | |||
| 36038 | { | |||
| 36039 | snprintf(buf, sizeof(buf), "%s %s (?)", ItemTooltips.getItemStatusAdjective(item->type, item->status).c_str(), item->getName()); | |||
| 36040 | } | |||
| 36041 | } | |||
| 36042 | else | |||
| 36043 | { | |||
| 36044 | if ( (item->type == TOOL_SENTRYBOT || item->type == TOOL_DUMMYBOT || item->type == TOOL_SPELLBOT | |||
| 36045 | || item->type == TOOL_GYROBOT) ) | |||
| 36046 | { | |||
| 36047 | int health = 100; | |||
| 36048 | if ( !item->tinkeringBotIsMaxHealth() ) | |||
| 36049 | { | |||
| 36050 | health = 25 * (item->appearance % 10); | |||
| 36051 | if ( health == 0 && item->status != BROKEN ) | |||
| 36052 | { | |||
| 36053 | health = 5; | |||
| 36054 | } | |||
| 36055 | } | |||
| 36056 | snprintf(buf, sizeof(buf), "%s %s (%d%%)", ItemTooltips.getItemStatusAdjective(item->type, item->status).c_str(), item->getName(), health); | |||
| 36057 | } | |||
| 36058 | else if ( item->type == ENCHANTED_FEATHER && item->identified ) | |||
| 36059 | { | |||
| 36060 | snprintf(buf, sizeof(buf), "%s %s (%d%%) (%+d)", ItemTooltips.getItemStatusAdjective(item->type, item->status).c_str(), | |||
| 36061 | item->getName(), item->appearance % ENCHANTED_FEATHER_MAX_DURABILITY, item->beatitude); | |||
| 36062 | } | |||
| 36063 | else if ( itemCategory(item) == BOOK ) | |||
| 36064 | { | |||
| 36065 | snprintf(buf, sizeof(buf), "%s %s", ItemTooltips.getItemStatusAdjective(item->type, item->status).c_str(), | |||
| 36066 | Language::get(4214)); // brand new copy of | |||
| 36067 | snprintf(buf2, sizeof(buf), "%s (%+d)", getBookLocalizedNameFromIndex(item->appearance % numbooks).c_str(), item->beatitude); | |||
| 36068 | } | |||
| 36069 | else | |||
| 36070 | { | |||
| 36071 | snprintf(buf, sizeof(buf), "%s %s (%+d)", ItemTooltips.getItemStatusAdjective(item->type, item->status).c_str(), item->getName(), item->beatitude); | |||
| 36072 | } | |||
| 36073 | } | |||
| 36074 | ||||
| 36075 | if ( strcmp(buf2, "") ) | |||
| 36076 | { | |||
| 36077 | numHeaderLines += 1; | |||
| 36078 | } | |||
| 36079 | ||||
| 36080 | size_t longestLine = 200; | |||
| 36081 | if ( auto textGet = Text::get(buf, font->getName(), 0xFFFFFFFF, 0) ) | |||
| 36082 | { | |||
| 36083 | if ( numHeaderLines == 1 && textGet->getWidth() > 300 ) | |||
| 36084 | { | |||
| 36085 | Field* f = new Field(1024); | |||
| 36086 | f->setText(buf); | |||
| 36087 | f->setSize(SDL_Rect{ 0, 0, 300, 0 }); | |||
| 36088 | f->reflowTextToFit(0); | |||
| 36089 | strcpy(buf, f->getText()); | |||
| 36090 | delete f; | |||
| 36091 | f = nullptr; | |||
| 36092 | for ( size_t c = 0; c < strlen(buf); ++c ) | |||
| 36093 | { | |||
| 36094 | if ( buf[c] == '\n' ) | |||
| 36095 | { | |||
| 36096 | buf[c] = '\0'; | |||
| 36097 | strcpy(buf2, buf + c + 1); | |||
| 36098 | std::string buf2Str = buf2; | |||
| 36099 | replace(buf2Str.begin(), buf2Str.end(), '\n', ' '); | |||
| 36100 | strcpy(buf2, buf2Str.c_str()); | |||
| 36101 | break; | |||
| 36102 | } | |||
| 36103 | } | |||
| 36104 | textGet = Text::get(buf, font->getName(), 0xFFFFFFFF, 0); | |||
| 36105 | numHeaderLines++; | |||
| 36106 | } | |||
| 36107 | longestLine = std::max(longestLine, (size_t)textGet->getWidth()); | |||
| 36108 | } | |||
| 36109 | if ( numHeaderLines > 1 ) | |||
| 36110 | { | |||
| 36111 | if ( auto textGet = Text::get(buf2, font->getName(), 0xFFFFFFFF, 0) ) | |||
| 36112 | { | |||
| 36113 | longestLine = std::max(longestLine, (size_t)textGet->getWidth()); | |||
| 36114 | } | |||
| 36115 | } | |||
| 36116 | tooltip.w = 16 + 16 + 8 + longestLine; | |||
| 36117 | ||||
| 36118 | if ( numHeaderLines > 1 ) | |||
| 36119 | { | |||
| 36120 | headerSize = 42; | |||
| 36121 | } | |||
| 36122 | else | |||
| 36123 | { | |||
| 36124 | headerSize = 28; | |||
| 36125 | } | |||
| 36126 | itemFrame->setSize(SDL_Rect{ | |||
| 36127 | tooltip.w - itemFrame->getSize().w - 16, | |||
| 36128 | headerSize + 4, | |||
| 36129 | itemFrame->getSize().w, | |||
| 36130 | itemFrame->getSize().h }); | |||
| 36131 | tooltip.h = itemFrame->getSize().h + 8 + headerSize; | |||
| 36132 | ||||
| 36133 | if ( itemWorldTooltipSurface ) | |||
| 36134 | { | |||
| 36135 | SDL_FreeSurface(itemWorldTooltipSurface); | |||
| 36136 | itemWorldTooltipSurface = nullptr; | |||
| 36137 | } | |||
| 36138 | itemWorldTooltipSurface = SDL_CreateRGBSurface(0, tooltip.w, tooltip.h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); | |||
| 36139 | ||||
| 36140 | SDL_Rect imgPos{ 0, 0, 0, 0 }; | |||
| 36141 | if ( numHeaderLines == 1 ) | |||
| 36142 | { | |||
| 36143 | if ( auto img = Image::get("*#images/ui/Inventory/tooltips/Hover_TL00.png") ) | |||
| 36144 | { | |||
| 36145 | imgPos.w = img->getWidth(); | |||
| 36146 | imgPos.h = img->getHeight(); | |||
| 36147 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36148 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &imgPos); | |||
| 36149 | } | |||
| 36150 | imgPos.x += imgPos.w; | |||
| 36151 | if ( auto img = Image::get("*#images/ui/Inventory/tooltips/Hover_T00.png") ) | |||
| 36152 | { | |||
| 36153 | imgPos.w = tooltip.w - imgPos.w * 2; | |||
| 36154 | imgPos.h = img->getHeight(); | |||
| 36155 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36156 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &imgPos); | |||
| 36157 | } | |||
| 36158 | imgPos.x += imgPos.w; | |||
| 36159 | if ( auto img = Image::get("*#images/ui/Inventory/tooltips/Hover_TR00.png") ) | |||
| 36160 | { | |||
| 36161 | imgPos.w = img->getWidth(); | |||
| 36162 | imgPos.h = img->getHeight(); | |||
| 36163 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36164 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &imgPos); | |||
| 36165 | } | |||
| 36166 | } | |||
| 36167 | else | |||
| 36168 | { | |||
| 36169 | if ( auto img = Image::get("*#images/ui/Inventory/tooltips/Hover_TL00_2x.png") ) | |||
| 36170 | { | |||
| 36171 | imgPos.w = img->getWidth(); | |||
| 36172 | imgPos.h = img->getHeight(); | |||
| 36173 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36174 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &imgPos); | |||
| 36175 | } | |||
| 36176 | imgPos.x += imgPos.w; | |||
| 36177 | if ( auto img = Image::get("*#images/ui/Inventory/tooltips/Hover_T00_2x.png") ) | |||
| 36178 | { | |||
| 36179 | imgPos.w = tooltip.w - imgPos.w * 2; | |||
| 36180 | imgPos.h = img->getHeight(); | |||
| 36181 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36182 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &imgPos); | |||
| 36183 | } | |||
| 36184 | imgPos.x += imgPos.w; | |||
| 36185 | if ( auto img = Image::get("*#images/ui/Inventory/tooltips/Hover_TR00_2x.png") ) | |||
| 36186 | { | |||
| 36187 | imgPos.w = img->getWidth(); | |||
| 36188 | imgPos.h = img->getHeight(); | |||
| 36189 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36190 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &imgPos); | |||
| 36191 | } | |||
| 36192 | } | |||
| 36193 | ||||
| 36194 | imgPos.x = 0; | |||
| 36195 | imgPos.y += imgPos.h; | |||
| 36196 | if ( auto img = Image::get("*#images/ui/Inventory/tooltips/Hover_L00.png") ) | |||
| 36197 | { | |||
| 36198 | imgPos.w = img->getWidth(); | |||
| 36199 | imgPos.h = tooltip.h - imgPos.h - 26; | |||
| 36200 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36201 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &imgPos); | |||
| 36202 | } | |||
| 36203 | imgPos.x += imgPos.w; | |||
| 36204 | if ( auto img = Image::get("*#images/ui/Inventory/tooltips/Hover_C00.png") ) | |||
| 36205 | { | |||
| 36206 | imgPos.w = tooltip.w - imgPos.w * 2; | |||
| 36207 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36208 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &imgPos); | |||
| 36209 | } | |||
| 36210 | imgPos.x += imgPos.w; | |||
| 36211 | if ( auto img = Image::get("*#images/ui/Inventory/tooltips/Hover_R00.png") ) | |||
| 36212 | { | |||
| 36213 | imgPos.w = img->getWidth(); | |||
| 36214 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36215 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &imgPos); | |||
| 36216 | } | |||
| 36217 | ||||
| 36218 | imgPos.x = 0; | |||
| 36219 | imgPos.y += imgPos.h; | |||
| 36220 | if ( auto img = Image::get("*#images/ui/Inventory/tooltips/Hover_BL01_NoPrompt.png") ) | |||
| 36221 | { | |||
| 36222 | imgPos.w = img->getWidth(); | |||
| 36223 | imgPos.h = img->getHeight(); | |||
| 36224 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36225 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &imgPos); | |||
| 36226 | } | |||
| 36227 | imgPos.x += imgPos.w; | |||
| 36228 | if ( auto img = Image::get("*#images/ui/Inventory/tooltips/Hover_B00_NoPrompt.png") ) | |||
| 36229 | { | |||
| 36230 | imgPos.w = tooltip.w - imgPos.w * 2; | |||
| 36231 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36232 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &imgPos); | |||
| 36233 | } | |||
| 36234 | imgPos.x += imgPos.w; | |||
| 36235 | if ( auto img = Image::get("*#images/ui/Inventory/tooltips/Hover_BR01_NoPrompt.png") ) | |||
| 36236 | { | |||
| 36237 | imgPos.w = img->getWidth(); | |||
| 36238 | imgPos.h = img->getHeight(); | |||
| 36239 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36240 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &imgPos); | |||
| 36241 | } | |||
| 36242 | } | |||
| 36243 | ||||
| 36244 | { | |||
| 36245 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get("images/ui/HUD/hotbar/HUD_Quickbar_Slot_Box_02.png")->getSurf()); | |||
| 36246 | SDL_Rect pos = SDL_Rect{ itemFrame->getSize().x, itemFrame->getSize().y, | |||
| 36247 | player.hotbar.getSlotSize(), player.hotbar.getSlotSize()}; | |||
| 36248 | SDL_BlitSurfaceSDL_UpperBlit(srcSurf, nullptr, itemWorldTooltipSurface, &pos); | |||
| 36249 | } | |||
| 36250 | ||||
| 36251 | for ( auto& f : itemFrame->getFrames() ) | |||
| 36252 | { | |||
| 36253 | SDL_Rect pos = itemFrame->getSize(); | |||
| 36254 | pos.x += f->getSize().x; | |||
| 36255 | pos.y += f->getSize().y; | |||
| 36256 | ||||
| 36257 | if ( f->isDisabled() ) { continue; } | |||
| 36258 | for ( auto& img : f->getImages() ) | |||
| 36259 | { | |||
| 36260 | if ( img->disabled ) { continue; } | |||
| 36261 | if ( img->path == "" ) { continue; } | |||
| 36262 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(Image::get(img->path.c_str())->getSurf()); | |||
| 36263 | Uint8 r, g, b, a; | |||
| 36264 | getColor(img->color, &r, &g, &b, &a); | |||
| 36265 | SDL_SetSurfaceAlphaMod(srcSurf, a); | |||
| 36266 | SDL_Rect imgPos = pos; | |||
| 36267 | imgPos.x += img->pos.x; | |||
| 36268 | imgPos.y += img->pos.y; | |||
| 36269 | imgPos.w = img->pos.w; | |||
| 36270 | imgPos.h = img->pos.h; | |||
| 36271 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &imgPos); | |||
| 36272 | } | |||
| 36273 | for ( auto& field : f->getFields() ) | |||
| 36274 | { | |||
| 36275 | if ( field->isDisabled() ) { continue; } | |||
| 36276 | SDL_Rect txtPos = pos; | |||
| 36277 | auto textGet = field->getTextObject(); | |||
| 36278 | int x = field->getSize().x; | |||
| 36279 | int y = field->getSize().y; | |||
| 36280 | if ( field->getHJustify() == Field::justify_t::RIGHT | |||
| 36281 | || field->getHJustify() == Field::justify_t::BOTTOM ) | |||
| 36282 | { | |||
| 36283 | x = field->getSize().x + field->getSize().w - textGet->getWidth(); | |||
| 36284 | } | |||
| 36285 | if ( field->getVJustify() == Field::justify_t::BOTTOM | |||
| 36286 | || field->getVJustify() == Field::justify_t::RIGHT ) | |||
| 36287 | { | |||
| 36288 | y = field->getSize().y + field->getSize().h - font->height(); | |||
| 36289 | } | |||
| 36290 | txtPos.x += x; | |||
| 36291 | txtPos.y += y; | |||
| 36292 | txtPos.w = field->getSize().w; | |||
| 36293 | txtPos.h = field->getSize().h; | |||
| 36294 | SDL_BlitSurfaceSDL_UpperBlit(const_cast<SDL_Surface*>(textGet->getSurf()), nullptr, itemWorldTooltipSurface, &txtPos); | |||
| 36295 | } | |||
| 36296 | } | |||
| 36297 | ||||
| 36298 | GLuint itemTexid = 0; | |||
| 36299 | SDL_Rect pos; | |||
| 36300 | if ( SDL_Surface* textSurf = const_cast<SDL_Surface*>(Text::get(buf, font->getName(), | |||
| 36301 | makeColor(67, 195, 157, 255), 0)->getSurf()) ) | |||
| 36302 | { | |||
| 36303 | pos.x = 16 + 4; | |||
| 36304 | pos.y = 2; | |||
| 36305 | if ( numHeaderLines > 1 ) | |||
| 36306 | { | |||
| 36307 | pos.y = -2; | |||
| 36308 | } | |||
| 36309 | SDL_BlitSurfaceSDL_UpperBlit(textSurf, nullptr, itemWorldTooltipSurface, &pos); | |||
| 36310 | } | |||
| 36311 | if ( numHeaderLines > 1 ) | |||
| 36312 | { | |||
| 36313 | if ( SDL_Surface* textSurf = const_cast<SDL_Surface*>(Text::get(buf2, font->getName(), | |||
| 36314 | hudColors.characterSheetHeadingText, 0)->getSurf()) ) | |||
| 36315 | { | |||
| 36316 | pos.x = 16 + 4; | |||
| 36317 | pos.y = (font->height() - 8); | |||
| 36318 | SDL_BlitSurfaceSDL_UpperBlit(textSurf, nullptr, itemWorldTooltipSurface, &pos); | |||
| 36319 | } | |||
| 36320 | } | |||
| 36321 | ||||
| 36322 | { | |||
| 36323 | SDL_Rect identifyPos = pos; | |||
| 36324 | std::string identifyStr = ItemTooltips.adjectives["item_identified_status"]["unidentified"]; | |||
| 36325 | if ( item->identified ) | |||
| 36326 | { | |||
| 36327 | if ( item->beatitude > 0 ) | |||
| 36328 | { | |||
| 36329 | identifyStr = ItemTooltips.adjectives["item_identified_status"]["blessed"]; | |||
| 36330 | } | |||
| 36331 | else if ( item->beatitude < 0 ) | |||
| 36332 | { | |||
| 36333 | identifyStr = ItemTooltips.adjectives["item_identified_status"]["cursed"]; | |||
| 36334 | } | |||
| 36335 | else | |||
| 36336 | { | |||
| 36337 | identifyStr = ItemTooltips.adjectives["item_identified_status"]["uncursed"]; | |||
| 36338 | } | |||
| 36339 | } | |||
| 36340 | identifyPos.y = headerSize; | |||
| 36341 | if ( auto textGet = Text::get(identifyStr.c_str(), font->getName(), | |||
| 36342 | hudColors.characterSheetNeutral, 0) ) | |||
| 36343 | { | |||
| 36344 | if ( SDL_Surface* textSurf = const_cast<SDL_Surface*>(textGet->getSurf()) ) | |||
| 36345 | { | |||
| 36346 | SDL_BlitSurfaceSDL_UpperBlit(textSurf, nullptr, itemWorldTooltipSurface, &identifyPos); | |||
| 36347 | } | |||
| 36348 | identifyPos.w = textGet->getWidth(); | |||
| 36349 | identifyPos.h = textGet->getHeight(); | |||
| 36350 | } | |||
| 36351 | ||||
| 36352 | SDL_Rect wgtPos = pos; | |||
| 36353 | wgtPos.y = identifyPos.y + identifyPos.h + 2; | |||
| 36354 | wgtPos.x = identifyPos.x; | |||
| 36355 | const char* wgtImg = "images/ui/Inventory/tooltips/HUD_Tooltip_Icon_WGT_00.png"; | |||
| 36356 | if ( auto imgGet = Image::get(wgtImg) ) | |||
| 36357 | { | |||
| 36358 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(imgGet->getSurf()); | |||
| 36359 | wgtPos.w = imgGet->getWidth(); | |||
| 36360 | wgtPos.h = imgGet->getHeight(); | |||
| 36361 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &wgtPos); | |||
| 36362 | ||||
| 36363 | char wgtBuf[32]; | |||
| 36364 | snprintf(wgtBuf, sizeof(wgtBuf), "%d", item->getWeight()); | |||
| 36365 | if ( auto textGet = Text::get(wgtBuf, font->getName(), | |||
| 36366 | hudColors.characterSheetNeutral, 0) ) | |||
| 36367 | { | |||
| 36368 | SDL_Surface* textSurf = const_cast<SDL_Surface*>(textGet->getSurf()); | |||
| 36369 | wgtPos.x += wgtPos.w + 4; | |||
| 36370 | wgtPos.y = wgtPos.y + wgtPos.h / 2 - font->height() / 2; | |||
| 36371 | if ( wgtPos.y % 2 == 1 ) | |||
| 36372 | { | |||
| 36373 | ++wgtPos.y; | |||
| 36374 | } | |||
| 36375 | SDL_BlitSurfaceSDL_UpperBlit(textSurf, nullptr, itemWorldTooltipSurface, &wgtPos); | |||
| 36376 | wgtPos.x += textGet->getWidth() + 8; | |||
| 36377 | } | |||
| 36378 | } | |||
| 36379 | ||||
| 36380 | SDL_Rect goldPos = wgtPos; | |||
| 36381 | goldPos.y = identifyPos.y + identifyPos.h; | |||
| 36382 | const char* goldImg = "images/ui/Inventory/tooltips/HUD_Tooltip_Icon_Money_00.png"; | |||
| 36383 | if ( auto imgGet = Image::get(goldImg) ) | |||
| 36384 | { | |||
| 36385 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(imgGet->getSurf()); | |||
| 36386 | goldPos.w = imgGet->getWidth(); | |||
| 36387 | goldPos.h = imgGet->getHeight(); | |||
| 36388 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, itemWorldTooltipSurface, &goldPos); | |||
| 36389 | ||||
| 36390 | char goldBuf[32]; | |||
| 36391 | if ( !item->identified && itemCategory(item) == GEM ) | |||
| 36392 | { | |||
| 36393 | snprintf(goldBuf, sizeof(goldBuf), "%d", items[GEM_GLASS].value); | |||
| 36394 | } | |||
| 36395 | else | |||
| 36396 | { | |||
| 36397 | snprintf(goldBuf, sizeof(goldBuf), "%d", items[item->type].value); | |||
| 36398 | } | |||
| 36399 | if ( SDL_Surface* textSurf = const_cast<SDL_Surface*>(Text::get(goldBuf, font->getName(), | |||
| 36400 | hudColors.characterSheetNeutral, 0)->getSurf()) ) | |||
| 36401 | { | |||
| 36402 | goldPos.x += goldPos.w + 4; | |||
| 36403 | goldPos.y = goldPos.y + goldPos.h / 2 - font->height() / 2; | |||
| 36404 | if ( goldPos.y % 2 == 1 ) | |||
| 36405 | { | |||
| 36406 | ++goldPos.y; | |||
| 36407 | } | |||
| 36408 | SDL_BlitSurfaceSDL_UpperBlit(textSurf, nullptr, itemWorldTooltipSurface, &goldPos); | |||
| 36409 | } | |||
| 36410 | } | |||
| 36411 | } | |||
| 36412 | return itemWorldTooltipSurface; | |||
| 36413 | } | |||
| 36414 | ||||
| 36415 | void Player::WorldUI_t::WorldTooltipDialogue_t::Dialogue_t::deactivate() | |||
| 36416 | { | |||
| 36417 | parent = 0; | |||
| 36418 | x = 0.0; | |||
| 36419 | y = 0.0; | |||
| 36420 | z = 0.0; | |||
| 36421 | active = false; | |||
| 36422 | init = false; | |||
| 36423 | draw = false; | |||
| 36424 | alpha = 0.0; | |||
| 36425 | spawnTick = 0; | |||
| 36426 | updatedThisTick = 0; | |||
| 36427 | expiryTicks = 0; | |||
| 36428 | dialogueStringLength = 0; | |||
| 36429 | dialogueStrFull = ""; | |||
| 36430 | dialogueStrCurrent = ""; | |||
| 36431 | int langEntry = 0; | |||
| 36432 | DialogueType_t dialogueType = DIALOGUE_NONE; | |||
| 36433 | if ( dialogueTooltipSurface ) | |||
| 36434 | { | |||
| 36435 | SDL_FreeSurface(dialogueTooltipSurface); | |||
| 36436 | dialogueTooltipSurface = nullptr; | |||
| 36437 | } | |||
| 36438 | } | |||
| 36439 | ||||
| 36440 | void Player::WorldUI_t::WorldTooltipDialogue_t::update() | |||
| 36441 | { | |||
| 36442 | playerDialogue.update(); | |||
| 36443 | for ( auto& d : sharedDialogues ) | |||
| 36444 | { | |||
| 36445 | d.second.update(); | |||
| 36446 | } | |||
| 36447 | for ( auto it = sharedDialogues.cbegin(); it != sharedDialogues.cend(); ) | |||
| 36448 | { | |||
| 36449 | if ( !it->second.active && it->second.alpha <= 0.0 | |||
| 36450 | && (ticks - it->second.spawnTick >= it->second.expiryTicks) ) | |||
| 36451 | { | |||
| 36452 | it = sharedDialogues.erase(it); | |||
| 36453 | } | |||
| 36454 | else | |||
| 36455 | { | |||
| 36456 | ++it; | |||
| 36457 | } | |||
| 36458 | } | |||
| 36459 | } | |||
| 36460 | ||||
| 36461 | void Player::WorldUI_t::WorldTooltipDialogue_t::Dialogue_t::update() | |||
| 36462 | { | |||
| 36463 | if ( !init ) | |||
| 36464 | { | |||
| 36465 | return; | |||
| 36466 | } | |||
| 36467 | if ( player == -1 ) | |||
| 36468 | { | |||
| 36469 | deactivate(); | |||
| 36470 | return; | |||
| 36471 | } | |||
| 36472 | bool singleDisplayDialogue = (this == &players[player]->worldUI.worldTooltipDialogue.playerDialogue); | |||
| 36473 | if ( client_disconnected[player] ) | |||
| 36474 | { | |||
| 36475 | active = false; | |||
| 36476 | } | |||
| 36477 | ||||
| 36478 | Entity* parentEnt = uidToEntity(parent); | |||
| 36479 | bool expired = false; | |||
| 36480 | if ( !parentEnt ) | |||
| 36481 | { | |||
| 36482 | active = false; | |||
| 36483 | expired = true; | |||
| 36484 | } | |||
| 36485 | else if ( ticks - spawnTick >= expiryTicks ) | |||
| 36486 | { | |||
| 36487 | active = false; | |||
| 36488 | expired = true; | |||
| 36489 | } | |||
| 36490 | ||||
| 36491 | ||||
| 36492 | auto& setting = WorldDialogueSettings_t::settings[dialogueType]; | |||
| 36493 | if ( parentEnt && setting.followEntity ) | |||
| 36494 | { | |||
| 36495 | /*if ( parentEnt->bUseRenderInterpolation ) | |||
| 36496 | { | |||
| 36497 | x = parentEnt->lerpRenderState.x.position * 16.0; | |||
| 36498 | y = parentEnt->lerpRenderState.y.position * 16.0; | |||
| 36499 | z = parentEnt->lerpRenderState.z.position + setting.offsetZ; | |||
| 36500 | } | |||
| 36501 | else*/ | |||
| 36502 | { | |||
| 36503 | x = parentEnt->x; | |||
| 36504 | y = parentEnt->y; | |||
| 36505 | z = parentEnt->z + setting.offsetZ; | |||
| 36506 | } | |||
| 36507 | } | |||
| 36508 | ||||
| 36509 | real_t dx, dy; | |||
| 36510 | auto& camera = cameras[player]; | |||
| 36511 | dx = x - camera.x * 16.0; | |||
| 36512 | dy = y - camera.y * 16.0; | |||
| 36513 | if ( dx * dx + dy * dy > setting.fadeDist * setting.fadeDist ) | |||
| 36514 | { | |||
| 36515 | active = false; | |||
| 36516 | } | |||
| 36517 | else if ( !singleDisplayDialogue && !expired ) | |||
| 36518 | { | |||
| 36519 | active = true; | |||
| 36520 | } | |||
| 36521 | ||||
| 36522 | if ( ticks != updatedThisTick ) | |||
| 36523 | { | |||
| 36524 | if ( active ) | |||
| 36525 | { | |||
| 36526 | alpha = std::min(1.0, alpha + .15); | |||
| 36527 | animZ -= animZ * 0.25; | |||
| 36528 | animZ = std::max(0.1, animZ); | |||
| 36529 | } | |||
| 36530 | else | |||
| 36531 | { | |||
| 36532 | alpha = std::max(0.0, alpha - .12); | |||
| 36533 | animZ += 0.05; | |||
| 36534 | animZ = std::min(1.5, animZ); | |||
| 36535 | if ( alpha <= 0.0 ) | |||
| 36536 | { | |||
| 36537 | if ( expired || singleDisplayDialogue ) | |||
| 36538 | { | |||
| 36539 | deactivate(); | |||
| 36540 | } | |||
| 36541 | return; | |||
| 36542 | } | |||
| 36543 | } | |||
| 36544 | } | |||
| 36545 | ||||
| 36546 | if ( setting.textDelay <= 0 ) | |||
| 36547 | { | |||
| 36548 | dialogueStrCurrent = dialogueStrFull; | |||
| 36549 | dialogueStringLength = dialogueStrFull.size(); | |||
| 36550 | } | |||
| 36551 | else if ( ticks - updatedThisTick > (Uint32)(setting.textDelay - 1) ) | |||
| 36552 | { | |||
| 36553 | size_t fullLen = dialogueStrFull.size(); | |||
| 36554 | if ( dialogueStringLength < fullLen ) | |||
| 36555 | { | |||
| 36556 | if ( dialogueStringLength + 1 == fullLen ) | |||
| 36557 | { | |||
| 36558 | dialogueStrCurrent = dialogueStrFull; | |||
| 36559 | } | |||
| 36560 | else | |||
| 36561 | { | |||
| 36562 | dialogueStrCurrent = dialogueStrFull.substr(0U, dialogueStringLength + 1); | |||
| 36563 | ++dialogueStringLength; | |||
| 36564 | } | |||
| 36565 | } | |||
| 36566 | else if ( dialogueStringLength > fullLen ) | |||
| 36567 | { | |||
| 36568 | dialogueStringLength = fullLen; | |||
| 36569 | } | |||
| 36570 | } | |||
| 36571 | draw = true; | |||
| 36572 | ||||
| 36573 | if ( ticks != updatedThisTick ) | |||
| 36574 | { | |||
| 36575 | blitDialogueTooltip(); | |||
| 36576 | } | |||
| 36577 | updatedThisTick = ticks; | |||
| 36578 | } | |||
| 36579 | ||||
| 36580 | void Player::WorldUI_t::WorldTooltipDialogue_t::createDialogueTooltip(Uint32 uid, | |||
| 36581 | Player::WorldUI_t::WorldTooltipDialogue_t::DialogueType_t type, char const * const message, ...) | |||
| 36582 | { | |||
| 36583 | if ( multiplayer == SERVER1 ) | |||
| 36584 | { | |||
| 36585 | if ( player.playernum != clientnum ) | |||
| 36586 | { | |||
| 36587 | if ( client_disconnected[player.playernum] ) | |||
| 36588 | { | |||
| 36589 | return; | |||
| 36590 | } | |||
| 36591 | char buf[1024] = { 0 }; | |||
| 36592 | ||||
| 36593 | va_list argptr; | |||
| 36594 | va_start(argptr, message)__builtin_va_start(argptr, message); | |||
| 36595 | vsnprintf(buf, sizeof(buf), message, argptr); | |||
| 36596 | va_end(argptr)__builtin_va_end(argptr); | |||
| 36597 | ||||
| 36598 | strcpy((char*)net_packet->data, "BUBL"); | |||
| 36599 | SDLNet_Write32(uid, &net_packet->data[4])_SDLNet_Write32(uid, &net_packet->data[4]); | |||
| 36600 | net_packet->data[8] = Uint8(type); | |||
| 36601 | strcpy((char*)(&net_packet->data[9]), buf); | |||
| 36602 | net_packet->address.host = net_clients[player.playernum - 1].host; | |||
| 36603 | net_packet->address.port = net_clients[player.playernum - 1].port; | |||
| 36604 | net_packet->len = 9 + strlen(buf) + 1; | |||
| 36605 | sendPacketSafe(net_sock, -1, net_packet, player.playernum - 1); | |||
| 36606 | return; | |||
| 36607 | } | |||
| 36608 | } | |||
| 36609 | ||||
| 36610 | Dialogue_t* d = &playerDialogue; | |||
| 36611 | if ( !(type == DIALOGUE_GRAVE || type == DIALOGUE_SIGNPOST | |||
| 36612 | || type == DIALOGUE_NPC) ) | |||
| 36613 | { | |||
| 36614 | if ( type == DIALOGUE_ATTACK && (sharedDialogues.find(uid) != sharedDialogues.end()) ) | |||
| 36615 | { | |||
| 36616 | if ( sharedDialogues[uid].dialogueType == DIALOGUE_ATTACK ) | |||
| 36617 | { | |||
| 36618 | return; // don't process combat taunts unless previous finished | |||
| 36619 | } | |||
| 36620 | } | |||
| 36621 | d = &sharedDialogues[uid]; | |||
| 36622 | } | |||
| 36623 | d->player = player.playernum; | |||
| 36624 | Uint32 oldUid = d->parent; | |||
| 36625 | real_t oldAlpha = d->alpha; | |||
| 36626 | real_t oldAnimZ = d->animZ; | |||
| 36627 | d->deactivate(); | |||
| 36628 | Entity* parentEnt = uidToEntity(uid); | |||
| 36629 | if ( !parentEnt ) | |||
| 36630 | { | |||
| 36631 | return; | |||
| 36632 | } | |||
| 36633 | d->parent = uid; | |||
| 36634 | ||||
| 36635 | char buf[1024] = { 0 }; | |||
| 36636 | ||||
| 36637 | va_list argptr; | |||
| 36638 | va_start(argptr, message)__builtin_va_start(argptr, message); | |||
| 36639 | vsnprintf(buf, sizeof(buf), message, argptr); | |||
| 36640 | va_end(argptr)__builtin_va_end(argptr); | |||
| 36641 | ||||
| 36642 | if (player.playernum == clientnum) | |||
| 36643 | { | |||
| 36644 | messagePlayer(player.playernum, MESSAGE_CHATTER, buf); | |||
| 36645 | } | |||
| 36646 | ||||
| 36647 | d->dialogueStrFull = buf; | |||
| 36648 | d->spawnTick = ticks; | |||
| 36649 | d->updatedThisTick = 0; | |||
| 36650 | d->dialogueType = type; | |||
| 36651 | ||||
| 36652 | auto& setting = WorldDialogueSettings_t::settings[d->dialogueType]; | |||
| 36653 | ||||
| 36654 | /*if ( parentEnt->bUseRenderInterpolation ) | |||
| 36655 | { | |||
| 36656 | d->x = parentEnt->lerpRenderState.x.position * 16.0; | |||
| 36657 | d->y = parentEnt->lerpRenderState.y.position * 16.0; | |||
| 36658 | d->z = parentEnt->lerpRenderState.z.position + setting.offsetZ; | |||
| 36659 | } | |||
| 36660 | else*/ | |||
| 36661 | { | |||
| 36662 | d->x = parentEnt->x; | |||
| 36663 | d->y = parentEnt->y; | |||
| 36664 | d->z = parentEnt->z + setting.offsetZ; | |||
| 36665 | } | |||
| 36666 | d->animZ = 1.5; | |||
| 36667 | d->drawScale = 0.1 + setting.scaleMod; | |||
| 36668 | ||||
| 36669 | d->active = true; | |||
| 36670 | d->init = true; | |||
| 36671 | d->alpha = 0.0; | |||
| 36672 | ||||
| 36673 | if ( d->parent == oldUid ) | |||
| 36674 | { | |||
| 36675 | d->alpha = oldAlpha; | |||
| 36676 | d->animZ = oldAnimZ; | |||
| 36677 | } | |||
| 36678 | ||||
| 36679 | if ( !d->dialogueField ) | |||
| 36680 | { | |||
| 36681 | d->dialogueField = new Field(1024); | |||
| 36682 | d->dialogueField->setFont("fonts/pixel_maz_multiline.ttf#16"); | |||
| 36683 | } | |||
| 36684 | d->dialogueField->setText(d->dialogueStrFull.c_str()); | |||
| 36685 | int maxWidth = setting.maxWidth; | |||
| 36686 | d->dialogueField->setSize(SDL_Rect{ 0, 0, maxWidth, 0 }); | |||
| 36687 | d->dialogueField->reflowTextToFit(0); | |||
| 36688 | int numLines = d->dialogueField->getNumTextLines(); | |||
| 36689 | if ( Font* actualFont = Font::get(d->dialogueField->getFont()) ) | |||
| 36690 | { | |||
| 36691 | auto textHeight = numLines * actualFont->height(true) + 16; | |||
| 36692 | if ( auto textGet = Text::get(d->dialogueField->getLongestLine().c_str(), | |||
| 36693 | d->dialogueField->getFont(), d->dialogueField->getTextColor(), | |||
| 36694 | d->dialogueField->getOutlineColor()) ) | |||
| 36695 | { | |||
| 36696 | d->dialogueField->setSize(SDL_Rect{ 0, 0, (int)textGet->getWidth() + 16, textHeight }); | |||
| 36697 | } | |||
| 36698 | else | |||
| 36699 | { | |||
| 36700 | d->dialogueField->setSize(SDL_Rect{ 0, 0, maxWidth, textHeight }); | |||
| 36701 | } | |||
| 36702 | } | |||
| 36703 | d->expiryTicks = setting.baseTicksToDisplay; | |||
| 36704 | if ( numLines > 1 ) | |||
| 36705 | { | |||
| 36706 | d->expiryTicks += (numLines - 1) * setting.extraTicksPerLine; | |||
| 36707 | } | |||
| 36708 | d->dialogueStrFull = d->dialogueField->getText(); | |||
| 36709 | ||||
| 36710 | if ( d->dialogueType == DIALOGUE_NPC ) | |||
| 36711 | { | |||
| 36712 | // insta-show the first line (e.g The NPC:) | |||
| 36713 | size_t found = d->dialogueStrFull.find('\n'); | |||
| 36714 | if ( found != std::string::npos ) | |||
| 36715 | { | |||
| 36716 | size_t foundColon = d->dialogueStrFull.find(':'); | |||
| 36717 | if ( foundColon != std::string::npos | |||
| 36718 | && foundColon < found ) | |||
| 36719 | { | |||
| 36720 | d->dialogueStringLength = found; | |||
| 36721 | ||||
| 36722 | while ( found != std::string::npos ) | |||
| 36723 | { | |||
| 36724 | if ( found + 1 < d->dialogueStrFull.length() ) | |||
| 36725 | { | |||
| 36726 | if ( d->dialogueStrFull[found + 1] != ' ' ) | |||
| 36727 | { | |||
| 36728 | d->dialogueStrFull.insert(found + 1, 1, ' '); | |||
| 36729 | ++found; | |||
| 36730 | } | |||
| 36731 | } | |||
| 36732 | found = d->dialogueStrFull.find('\n', found + 1); | |||
| 36733 | } | |||
| 36734 | } | |||
| 36735 | } | |||
| 36736 | d->dialogueField->setText(d->dialogueStrFull.c_str()); | |||
| 36737 | } | |||
| 36738 | } | |||
| 36739 | ||||
| 36740 | SDL_Surface* Player::WorldUI_t::WorldTooltipDialogue_t::Dialogue_t::blitDialogueTooltip() | |||
| 36741 | { | |||
| 36742 | auto& setting = WorldDialogueSettings_t::settings[dialogueType]; | |||
| 36743 | const int pointerExtraHeight = 16; | |||
| 36744 | SDL_Rect tooltip{ 0, 0, dialogueField->getSize().w, dialogueField->getSize().h }; | |||
| 36745 | tooltip.h += 16 + setting.padx * 2 + pointerExtraHeight; | |||
| 36746 | tooltip.w += 16 + setting.pady * 2; | |||
| 36747 | const int numLines = dialogueField->getNumTextLines(); | |||
| 36748 | if ( numLines > 1 ) | |||
| 36749 | { | |||
| 36750 | tooltip.h += setting.padAfterFirstLine; | |||
| 36751 | } | |||
| 36752 | ||||
| 36753 | if ( dialogueTooltipSurface ) | |||
| 36754 | { | |||
| 36755 | SDL_FreeSurface(dialogueTooltipSurface); | |||
| 36756 | dialogueTooltipSurface = nullptr; | |||
| 36757 | } | |||
| 36758 | ||||
| 36759 | dialogueTooltipSurface = SDL_CreateRGBSurface(0, tooltip.w, tooltip.h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); | |||
| 36760 | ||||
| 36761 | SDL_Rect imgPos{ 0, 0, 0, 0 }; | |||
| 36762 | if ( dialogueType == DIALOGUE_GRAVE ) | |||
| 36763 | { | |||
| 36764 | dialogueField->setTextColor(makeColor(51, 45, 59, 255)); | |||
| 36765 | dialogueField->setOutlineColor(makeColor(115, 127, 134, 255)); | |||
| 36766 | ||||
| 36767 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Grave_TL.png") ) | |||
| 36768 | { | |||
| 36769 | imgPos.w = img->getWidth(); | |||
| 36770 | imgPos.h = img->getHeight(); | |||
| 36771 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36772 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36773 | } | |||
| 36774 | imgPos.x += imgPos.w; | |||
| 36775 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Grave_T.png") ) | |||
| 36776 | { | |||
| 36777 | imgPos.w = tooltip.w - imgPos.w * 2; | |||
| 36778 | imgPos.h = img->getHeight(); | |||
| 36779 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36780 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36781 | } | |||
| 36782 | imgPos.x += imgPos.w; | |||
| 36783 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Grave_TR.png") ) | |||
| 36784 | { | |||
| 36785 | imgPos.w = img->getWidth(); | |||
| 36786 | imgPos.h = img->getHeight(); | |||
| 36787 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36788 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36789 | } | |||
| 36790 | ||||
| 36791 | imgPos.x = 0; | |||
| 36792 | imgPos.y += imgPos.h; | |||
| 36793 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Grave_L.png") ) | |||
| 36794 | { | |||
| 36795 | imgPos.w = img->getWidth(); | |||
| 36796 | imgPos.h = tooltip.h - imgPos.h - 26 - pointerExtraHeight; | |||
| 36797 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36798 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36799 | } | |||
| 36800 | imgPos.x += imgPos.w; | |||
| 36801 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Grave_Color.png") ) | |||
| 36802 | { | |||
| 36803 | imgPos.w = tooltip.w - imgPos.w * 2; | |||
| 36804 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36805 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36806 | } | |||
| 36807 | imgPos.x += imgPos.w; | |||
| 36808 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Grave_R.png") ) | |||
| 36809 | { | |||
| 36810 | imgPos.w = img->getWidth(); | |||
| 36811 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36812 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36813 | } | |||
| 36814 | ||||
| 36815 | imgPos.x = 0; | |||
| 36816 | imgPos.y += imgPos.h; | |||
| 36817 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Grave_BL.png") ) | |||
| 36818 | { | |||
| 36819 | imgPos.w = img->getWidth(); | |||
| 36820 | imgPos.h = img->getHeight(); | |||
| 36821 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36822 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36823 | } | |||
| 36824 | imgPos.x += imgPos.w; | |||
| 36825 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Grave_B.png") ) | |||
| 36826 | { | |||
| 36827 | imgPos.w = tooltip.w - imgPos.w * 2; | |||
| 36828 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36829 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36830 | } | |||
| 36831 | imgPos.x += imgPos.w; | |||
| 36832 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Grave_BR.png") ) | |||
| 36833 | { | |||
| 36834 | imgPos.w = img->getWidth(); | |||
| 36835 | imgPos.h = img->getHeight(); | |||
| 36836 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36837 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36838 | } | |||
| 36839 | ||||
| 36840 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Grave_Pointer.png") ) | |||
| 36841 | { | |||
| 36842 | imgPos.x = tooltip.w / 2; | |||
| 36843 | if ( imgPos.x % 2 == 1 ) | |||
| 36844 | { | |||
| 36845 | ++imgPos.x; | |||
| 36846 | } | |||
| 36847 | imgPos.y += imgPos.h - 6; | |||
| 36848 | imgPos.w = img->getWidth(); | |||
| 36849 | imgPos.h = img->getHeight(); | |||
| 36850 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36851 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36852 | } | |||
| 36853 | } | |||
| 36854 | else if ( dialogueType == DIALOGUE_SIGNPOST ) | |||
| 36855 | { | |||
| 36856 | dialogueField->setTextColor(makeColor(29, 16, 11, 255)); | |||
| 36857 | dialogueField->setOutlineColor(makeColor(82, 66, 60, 255)); | |||
| 36858 | ||||
| 36859 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Sign_TL.png") ) | |||
| 36860 | { | |||
| 36861 | imgPos.w = img->getWidth(); | |||
| 36862 | imgPos.h = img->getHeight(); | |||
| 36863 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36864 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36865 | } | |||
| 36866 | imgPos.x += imgPos.w; | |||
| 36867 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Sign_T.png") ) | |||
| 36868 | { | |||
| 36869 | imgPos.w = tooltip.w - imgPos.w * 2; | |||
| 36870 | imgPos.h = img->getHeight(); | |||
| 36871 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36872 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36873 | } | |||
| 36874 | imgPos.x += imgPos.w; | |||
| 36875 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Sign_TR.png") ) | |||
| 36876 | { | |||
| 36877 | imgPos.w = img->getWidth(); | |||
| 36878 | imgPos.h = img->getHeight(); | |||
| 36879 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36880 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36881 | } | |||
| 36882 | ||||
| 36883 | imgPos.x = 0; | |||
| 36884 | imgPos.y += imgPos.h; | |||
| 36885 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Sign_L.png") ) | |||
| 36886 | { | |||
| 36887 | imgPos.w = img->getWidth(); | |||
| 36888 | imgPos.h = tooltip.h - imgPos.h - 26 - pointerExtraHeight; | |||
| 36889 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36890 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36891 | } | |||
| 36892 | imgPos.x += imgPos.w; | |||
| 36893 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Sign_Color.png") ) | |||
| 36894 | { | |||
| 36895 | imgPos.w = tooltip.w - imgPos.w * 2; | |||
| 36896 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36897 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36898 | } | |||
| 36899 | imgPos.x += imgPos.w; | |||
| 36900 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Sign_R.png") ) | |||
| 36901 | { | |||
| 36902 | imgPos.w = img->getWidth(); | |||
| 36903 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36904 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36905 | } | |||
| 36906 | ||||
| 36907 | imgPos.x = 0; | |||
| 36908 | imgPos.y += imgPos.h; | |||
| 36909 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Sign_BL.png") ) | |||
| 36910 | { | |||
| 36911 | imgPos.w = img->getWidth(); | |||
| 36912 | imgPos.h = img->getHeight(); | |||
| 36913 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36914 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36915 | } | |||
| 36916 | imgPos.x += imgPos.w; | |||
| 36917 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Sign_B.png") ) | |||
| 36918 | { | |||
| 36919 | imgPos.w = tooltip.w - imgPos.w * 2; | |||
| 36920 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36921 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36922 | } | |||
| 36923 | imgPos.x += imgPos.w; | |||
| 36924 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Sign_BR.png") ) | |||
| 36925 | { | |||
| 36926 | imgPos.w = img->getWidth(); | |||
| 36927 | imgPos.h = img->getHeight(); | |||
| 36928 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36929 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36930 | } | |||
| 36931 | ||||
| 36932 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_Sign_Pointer.png") ) | |||
| 36933 | { | |||
| 36934 | imgPos.x = tooltip.w / 2; | |||
| 36935 | if ( imgPos.x % 2 == 1 ) | |||
| 36936 | { | |||
| 36937 | ++imgPos.x; | |||
| 36938 | } | |||
| 36939 | imgPos.y += imgPos.h - 6; | |||
| 36940 | imgPos.w = img->getWidth(); | |||
| 36941 | imgPos.h = img->getHeight(); | |||
| 36942 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36943 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36944 | } | |||
| 36945 | } | |||
| 36946 | else if ( dialogueType == DIALOGUE_NPC | |||
| 36947 | || dialogueType == DIALOGUE_FOLLOWER_CMD | |||
| 36948 | || dialogueType == DIALOGUE_BROADCAST | |||
| 36949 | || dialogueType == DIALOGUE_ATTACK ) | |||
| 36950 | { | |||
| 36951 | dialogueField->setTextColor(makeColor(29, 16, 11, 255)); | |||
| 36952 | dialogueField->setOutlineColor(makeColor(186, 169, 128, 255)); | |||
| 36953 | ||||
| 36954 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_NPC_TL.png") ) | |||
| 36955 | { | |||
| 36956 | imgPos.w = img->getWidth(); | |||
| 36957 | imgPos.h = img->getHeight(); | |||
| 36958 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36959 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36960 | } | |||
| 36961 | imgPos.x += imgPos.w; | |||
| 36962 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_NPC_T.png") ) | |||
| 36963 | { | |||
| 36964 | imgPos.w = tooltip.w - imgPos.w * 2; | |||
| 36965 | imgPos.h = img->getHeight(); | |||
| 36966 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36967 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36968 | } | |||
| 36969 | imgPos.x += imgPos.w; | |||
| 36970 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_NPC_TR.png") ) | |||
| 36971 | { | |||
| 36972 | imgPos.w = img->getWidth(); | |||
| 36973 | imgPos.h = img->getHeight(); | |||
| 36974 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36975 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36976 | } | |||
| 36977 | ||||
| 36978 | imgPos.x = 0; | |||
| 36979 | imgPos.y += imgPos.h; | |||
| 36980 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_NPC_L.png") ) | |||
| 36981 | { | |||
| 36982 | imgPos.w = img->getWidth(); | |||
| 36983 | imgPos.h = tooltip.h - imgPos.h - 26 - pointerExtraHeight; | |||
| 36984 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36985 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36986 | } | |||
| 36987 | imgPos.x += imgPos.w; | |||
| 36988 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_NPC_Color.png") ) | |||
| 36989 | { | |||
| 36990 | imgPos.w = tooltip.w - imgPos.w * 2; | |||
| 36991 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36992 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 36993 | } | |||
| 36994 | imgPos.x += imgPos.w; | |||
| 36995 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_NPC_R.png") ) | |||
| 36996 | { | |||
| 36997 | imgPos.w = img->getWidth(); | |||
| 36998 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 36999 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 37000 | } | |||
| 37001 | ||||
| 37002 | imgPos.x = 0; | |||
| 37003 | imgPos.y += imgPos.h; | |||
| 37004 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_NPC_BL.png") ) | |||
| 37005 | { | |||
| 37006 | imgPos.w = img->getWidth(); | |||
| 37007 | imgPos.h = img->getHeight(); | |||
| 37008 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 37009 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 37010 | } | |||
| 37011 | imgPos.x += imgPos.w; | |||
| 37012 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_NPC_B.png") ) | |||
| 37013 | { | |||
| 37014 | imgPos.w = tooltip.w - imgPos.w * 2; | |||
| 37015 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 37016 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 37017 | } | |||
| 37018 | imgPos.x += imgPos.w; | |||
| 37019 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_NPC_BR.png") ) | |||
| 37020 | { | |||
| 37021 | imgPos.w = img->getWidth(); | |||
| 37022 | imgPos.h = img->getHeight(); | |||
| 37023 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 37024 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 37025 | } | |||
| 37026 | ||||
| 37027 | if ( auto img = Image::get("*#images/ui/TextBubbles/Textbox_NPC_Pointer.png") ) | |||
| 37028 | { | |||
| 37029 | imgPos.x = tooltip.w / 2; | |||
| 37030 | if ( imgPos.x % 2 == 1 ) | |||
| 37031 | { | |||
| 37032 | ++imgPos.x; | |||
| 37033 | } | |||
| 37034 | imgPos.y += imgPos.h - 6; | |||
| 37035 | imgPos.w = img->getWidth(); | |||
| 37036 | imgPos.h = img->getHeight(); | |||
| 37037 | SDL_Surface* srcSurf = const_cast<SDL_Surface*>(img->getSurf()); | |||
| 37038 | SDL_BlitScaledSDL_UpperBlitScaled(srcSurf, nullptr, dialogueTooltipSurface, &imgPos); | |||
| 37039 | } | |||
| 37040 | } | |||
| 37041 | ||||
| 37042 | SDL_Rect txtPos{ 16 + setting.padx, 9 + setting.pady, 0, 0 }; | |||
| 37043 | int fontHeight = Font::get(dialogueField->getFont())->height(true); | |||
| 37044 | std::string buf; | |||
| 37045 | int linesDone = 0; | |||
| 37046 | for ( size_t i = 0; i < dialogueStrCurrent.length(); ++i ) | |||
| 37047 | { | |||
| 37048 | if ( dialogueStrCurrent[i] == '\n' || i == dialogueStrCurrent.length() - 1 ) | |||
| 37049 | { | |||
| 37050 | if ( i == dialogueStrCurrent.length() - 1 | |||
| 37051 | && dialogueStrCurrent[i] != '\r' | |||
| 37052 | && dialogueStrCurrent[i] != '\n' ) | |||
| 37053 | { | |||
| 37054 | buf += dialogueStrCurrent[i]; | |||
| 37055 | } | |||
| 37056 | if ( auto textGet = Text::get(buf.c_str(), dialogueField->getFont(), | |||
| 37057 | dialogueField->getTextColor(), dialogueField->getOutlineColor()) ) | |||
| 37058 | { | |||
| 37059 | bool quoteOffsetY = 0; | |||
| 37060 | size_t foundEOL = dialogueStrCurrent.find('\0', i + 1); | |||
| 37061 | size_t foundNewLine = dialogueStrCurrent.find('\n', i + 1); | |||
| 37062 | size_t foundQuote = dialogueStrCurrent.find('\"', i + 1); | |||
| 37063 | if ( foundNewLine != std::string::npos && foundEOL != std::string::npos | |||
| 37064 | && foundNewLine < foundEOL ) | |||
| 37065 | { | |||
| 37066 | if ( foundQuote < foundNewLine ) | |||
| 37067 | { | |||
| 37068 | // this line has a quote after first char | |||
| 37069 | // adjust line spacing to account for offset quote introduces | |||
| 37070 | quoteOffsetY = -2; | |||
| 37071 | } | |||
| 37072 | } | |||
| 37073 | else if ( foundEOL != std::string::npos ) | |||
| 37074 | { | |||
| 37075 | if ( foundQuote < foundEOL ) | |||
| 37076 | { | |||
| 37077 | // this line has a quote after first char | |||
| 37078 | // adjust line spacing to account for offset quote introduces | |||
| 37079 | quoteOffsetY = -2; | |||
| 37080 | } | |||
| 37081 | } | |||
| 37082 | txtPos.y += quoteOffsetY; | |||
| 37083 | SDL_BlitSurfaceSDL_UpperBlit(const_cast<SDL_Surface*>(textGet->getSurf()), nullptr, dialogueTooltipSurface, &txtPos); | |||
| 37084 | txtPos.y -= quoteOffsetY; | |||
| 37085 | txtPos.y += fontHeight; | |||
| 37086 | if ( linesDone == 0 ) | |||
| 37087 | { | |||
| 37088 | txtPos.y += setting.padAfterFirstLine; | |||
| 37089 | } | |||
| 37090 | } | |||
| 37091 | buf = ""; | |||
| 37092 | ++linesDone; | |||
| 37093 | continue; | |||
| 37094 | } | |||
| 37095 | else if ( dialogueStrCurrent[i] != '\r' ) | |||
| 37096 | { | |||
| 37097 | buf += dialogueStrCurrent[i]; | |||
| 37098 | } | |||
| 37099 | } | |||
| 37100 | return dialogueTooltipSurface; | |||
| 37101 | } | |||
| 37102 | ||||
| 37103 | void handleDamageIndicatorTicks() | |||
| 37104 | { | |||
| 37105 | for ( int i = 0; i < MAXPLAYERS4; ++i ) | |||
| 37106 | { | |||
| 37107 | for ( auto& ind : DamageIndicatorHandler.indicators[i] ) | |||
| 37108 | { | |||
| 37109 | if ( ind.ticks > 0 ) | |||
| 37110 | { | |||
| 37111 | --ind.ticks; | |||
| 37112 | } | |||
| 37113 | } | |||
| 37114 | } | |||
| 37115 | } | |||
| 37116 | ||||
| 37117 | void DamageIndicatorHandler_t::update() | |||
| 37118 | { | |||
| 37119 | for ( int i = 0; i < MAXPLAYERS4; ++i ) | |||
| 37120 | { | |||
| 37121 | for ( auto it = indicators[i].begin(); it != indicators[i].end(); ) | |||
| 37122 | { | |||
| 37123 | it->process(); | |||
| 37124 | if ( it->expired ) | |||
| 37125 | { | |||
| 37126 | it = indicators[i].erase(it); | |||
| 37127 | } | |||
| 37128 | else | |||
| 37129 | { | |||
| 37130 | ++it; | |||
| 37131 | } | |||
| 37132 | } | |||
| 37133 | } | |||
| 37134 | } | |||
| 37135 | void DamageIndicatorHandler_t::insert(const int player, const real_t _x, const real_t _y, const bool damaged) | |||
| 37136 | { | |||
| 37137 | for ( auto it = indicators[player].begin(); it != indicators[player].end(); ++it ) | |||
| 37138 | { | |||
| 37139 | if ( !it->expired && it->x == _x && it->y == _y && it->hitDealtDamage == damaged ) | |||
| 37140 | { | |||
| 37141 | // matching, delete this one | |||
| 37142 | indicators[player].erase(it); | |||
| 37143 | break; | |||
| 37144 | } | |||
| 37145 | } | |||
| 37146 | indicators[player].push_back(DamageIndicator_t(player)); | |||
| 37147 | auto& i = indicators[player].at(indicators[player].size() - 1); | |||
| 37148 | i.alpha = 255.0; | |||
| 37149 | i.ticks = damageIndicatorSettings.deleteAfterTicks; | |||
| 37150 | i.x = _x; | |||
| 37151 | i.y = _y; | |||
| 37152 | i.flashTicks = ::ticks; | |||
| 37153 | i.flashAnimState = -1; | |||
| 37154 | i.hitDealtDamage = damaged; | |||
| 37155 | } | |||
| 37156 | ||||
| 37157 | static ConsoleVariable<int> cvar_indicatoranimdebug("/indicatoranimdebug", 1); | |||
| 37158 | ||||
| 37159 | void DamageIndicatorHandler_t::DamageIndicator_t::process() | |||
| 37160 | { | |||
| 37161 | if ( expired ) | |||
| 37162 | { | |||
| 37163 | return; | |||
| 37164 | } | |||
| 37165 | double tangent = atan2(y / 16 - cameras[player].y, x / 16 - cameras[player].x); | |||
| 37166 | double angle = tangent - cameras[player].ang; | |||
| 37167 | angle += 3 * PI3.14159265358979323846 / 2; | |||
| 37168 | while ( angle >= PI3.14159265358979323846 ) | |||
| 37169 | { | |||
| 37170 | angle -= PI3.14159265358979323846 * 2; | |||
| 37171 | } | |||
| 37172 | while ( angle < -PI3.14159265358979323846 ) | |||
| 37173 | { | |||
| 37174 | angle += PI3.14159265358979323846 * 2; | |||
| 37175 | } | |||
| 37176 | ||||
| 37177 | const int framesPerAnimation = 1 * *cvar_indicatoranimdebug; | |||
| 37178 | const int numAnimationFrames = damageIndicatorSettings.deleteAfterTicks * *cvar_indicatoranimdebug; | |||
| 37179 | auto layout = DamageIndicatorSettings_t::LAYOUT_DEFAULT; | |||
| 37180 | if ( players[player]->bUseCompactGUIHeight() && players[player]->bUseCompactGUIWidth() ) | |||
| 37181 | { | |||
| 37182 | layout = DamageIndicatorSettings_t::LAYOUT_4P; | |||
| 37183 | } | |||
| 37184 | else if ( !players[player]->bUseCompactGUIHeight() && players[player]->bUseCompactGUIWidth() ) | |||
| 37185 | { | |||
| 37186 | layout = DamageIndicatorSettings_t::LAYOUT_2P_TALL; | |||
| 37187 | } | |||
| 37188 | else if ( players[player]->bUseCompactGUIHeight() && !players[player]->bUseCompactGUIWidth() ) | |||
| 37189 | { | |||
| 37190 | layout = DamageIndicatorSettings_t::LAYOUT_2P_WIDE; | |||
| 37191 | } | |||
| 37192 | size = damageIndicatorSettings.settings[layout].image_size; | |||
| 37193 | auto& indicatorDamagePaths = damageIndicatorSettings.indicatorDamageFramePaths; | |||
| 37194 | auto& indicatorBlockPaths = damageIndicatorSettings.indicatorBlockedFramePaths; | |||
| 37195 | std::string imagePath = hitDealtDamage ? indicatorDamagePaths[0] : indicatorBlockPaths[0]; | |||
| 37196 | if ( flashTicks > 0 ) | |||
| 37197 | { | |||
| 37198 | if ( flashAnimState > numAnimationFrames ) | |||
| 37199 | { | |||
| 37200 | flashTicks = 0; | |||
| 37201 | flashAnimState = -1; | |||
| 37202 | alpha = 0.0; | |||
| 37203 | } | |||
| 37204 | else | |||
| 37205 | { | |||
| 37206 | if ( ::ticks == flashTicks ) | |||
| 37207 | { | |||
| 37208 | flashAnimState = 1; | |||
| 37209 | flashProcessedOnTick = ::ticks; | |||
| 37210 | } | |||
| 37211 | else if ( (flashProcessedOnTick != ::ticks) | |||
| 37212 | && (::ticks > flashTicks) | |||
| 37213 | && (::ticks - flashTicks) % framesPerAnimation == 0 ) | |||
| 37214 | { | |||
| 37215 | ++flashAnimState; | |||
| 37216 | flashProcessedOnTick = ::ticks; | |||
| 37217 | } | |||
| 37218 | ||||
| 37219 | if ( flashAnimState <= 6 ) | |||
| 37220 | { | |||
| 37221 | alpha = 255.0; | |||
| 37222 | } | |||
| 37223 | ||||
| 37224 | if ( flashAnimState == 0 ) | |||
| 37225 | { | |||
| 37226 | imagePath = hitDealtDamage ? indicatorDamagePaths[0] : indicatorBlockPaths[0]; | |||
| 37227 | } | |||
| 37228 | else if ( flashAnimState >= 1 && flashAnimState <= 2 ) | |||
| 37229 | { | |||
| 37230 | imagePath = hitDealtDamage ? indicatorDamagePaths[0] : indicatorBlockPaths[0]; | |||
| 37231 | } | |||
| 37232 | else if ( flashAnimState == 3 ) | |||
| 37233 | { | |||
| 37234 | imagePath = hitDealtDamage ? indicatorDamagePaths[2] : indicatorBlockPaths[2]; | |||
| 37235 | } | |||
| 37236 | else if ( flashAnimState >= 4 && flashAnimState <= 5 ) | |||
| 37237 | { | |||
| 37238 | imagePath = hitDealtDamage ? indicatorDamagePaths[1] : indicatorBlockPaths[1]; | |||
| 37239 | } | |||
| 37240 | else if ( flashAnimState == 6 ) | |||
| 37241 | { | |||
| 37242 | imagePath = hitDealtDamage ? indicatorDamagePaths[3] : indicatorBlockPaths[3]; | |||
| 37243 | } | |||
| 37244 | else if ( flashAnimState >= damageIndicatorSettings.fadeAfterTicks ) | |||
| 37245 | { | |||
| 37246 | imagePath = hitDealtDamage ? indicatorDamagePaths[0] : indicatorBlockPaths[0]; | |||
| 37247 | int decrement = 20; | |||
| 37248 | real_t fpsScale = (getFPSScale(60.0)) / damageIndicatorSettings.fadeSpeed; | |||
| 37249 | decrement *= fpsScale; | |||
| 37250 | alpha = std::max(0, (int)alpha - decrement); | |||
| 37251 | } | |||
| 37252 | } | |||
| 37253 | } | |||
| 37254 | ||||
| 37255 | switch ( size ) | |||
| 37256 | { | |||
| 37257 | case 3: | |||
| 37258 | imagePath += "_3x.png"; | |||
| 37259 | break; | |||
| 37260 | case 2: | |||
| 37261 | imagePath += "_2x.png"; | |||
| 37262 | break; | |||
| 37263 | case 1: | |||
| 37264 | default: | |||
| 37265 | imagePath += "_1x.png"; | |||
| 37266 | break; | |||
| 37267 | } | |||
| 37268 | ||||
| 37269 | if ( auto imgGet = Image::get(imagePath.c_str()) ) | |||
| 37270 | { | |||
| 37271 | SDL_Rect pos; | |||
| 37272 | pos.x = players[player]->camera_midx(); | |||
| 37273 | pos.y = players[player]->camera_midy(); | |||
| 37274 | const float factorX = (float)xres / Frame::virtualScreenX; | |||
| 37275 | const float factorY = (float)yres / Frame::virtualScreenY; | |||
| 37276 | pos.x += damageIndicatorSettings.settings[layout].radius_x * cos(angle) * factorX; | |||
| 37277 | pos.y += damageIndicatorSettings.settings[layout].radius_y * sin(angle) * factorY; | |||
| 37278 | pos.w = imgGet->getWidth() * factorX; | |||
| 37279 | pos.h = imgGet->getHeight() * factorY; | |||
| 37280 | if ( stats[player]->HP > 0 ) | |||
| 37281 | { | |||
| 37282 | const SDL_Rect viewport{ 0, 0, xres, yres }; | |||
| 37283 | imgGet->drawRotated(nullptr, pos, viewport, makeColor(255, 255, 255, (Uint8)alpha), angle); | |||
| 37284 | } | |||
| 37285 | } | |||
| 37286 | ||||
| 37287 | if ( alpha <= 0 || ticks == 0 ) | |||
| 37288 | { | |||
| 37289 | expired = true; | |||
| 37290 | } | |||
| 37291 | } | |||
| 37292 | ||||
| 37293 | void createLevelUpFrame(const int player) | |||
| 37294 | { | |||
| 37295 | auto& hud_t = players[player]->hud; | |||
| 37296 | hud_t.levelupFrame = gameUIFrame[player]->addFrame("levelup"); | |||
| 37297 | hud_t.levelupFrame->setHollow(true); | |||
| 37298 | hud_t.levelupFrame->setInheritParentFrameOpacity(false); | |||
| 37299 | hud_t.levelupFrame->setOpacity(100.0); | |||
| 37300 | hud_t.levelupFrame->setDisabled(true); | |||
| 37301 | hud_t.levelupFrame->setOwner(player); | |||
| 37302 | ||||
| 37303 | auto lvlupImg = hud_t.levelupFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "images/ui/HUD/lvluptext.png", "lvl up img"); | |||
| 37304 | lvlupImg->disabled = true; | |||
| 37305 | ||||
| 37306 | auto statsFrame = hud_t.levelupFrame->addFrame("stats"); | |||
| 37307 | statsFrame->setDisabled(true); | |||
| 37308 | statsFrame->setHollow(true); | |||
| 37309 | char name[32]; | |||
| 37310 | std::string font = "fonts/pixelmix.ttf#16#2"; | |||
| 37311 | for ( int i = 0; i < 6; ++i ) | |||
| 37312 | { | |||
| 37313 | snprintf(name, sizeof(name), "stat %d", i); | |||
| 37314 | auto statFrame = statsFrame->addFrame(name); | |||
| 37315 | statFrame->setDisabled(true); | |||
| 37316 | statFrame->setHollow(true); | |||
| 37317 | statFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "stat img"); | |||
| 37318 | ||||
| 37319 | auto statCurrentTxt = statFrame->addField("stat current", 32); | |||
| 37320 | statCurrentTxt->setFont(font.c_str()); | |||
| 37321 | statCurrentTxt->setHJustify(Field::justify_t::RIGHT); | |||
| 37322 | statCurrentTxt->setVJustify(Field::justify_t::TOP); | |||
| 37323 | statCurrentTxt->setText("0"); | |||
| 37324 | ||||
| 37325 | auto statIncreaseTxt = statFrame->addField("stat increase", 32); | |||
| 37326 | statIncreaseTxt->setFont(font.c_str()); | |||
| 37327 | statIncreaseTxt->setHJustify(Field::justify_t::LEFT); | |||
| 37328 | statIncreaseTxt->setVJustify(Field::justify_t::TOP); | |||
| 37329 | statIncreaseTxt->setText("0"); | |||
| 37330 | } | |||
| 37331 | } | |||
| 37332 | ||||
| 37333 | static ConsoleVariable<int> cvar_lvlup_sfx("/lvlup_sfx", 526); | |||
| 37334 | Uint32 levelupSoundDelay = 0; | |||
| 37335 | void LevelUpAnimation_t::addLevelUp(const int currentLvl, const int increaseLvl, std::vector<LevelUp_t::StatUp_t>& statInfo) | |||
| 37336 | { | |||
| 37337 | if ( lvlUps.size() > 2 ) | |||
| 37338 | { | |||
| 37339 | // stack everything onto the back | |||
| 37340 | auto& lvlUp = lvlUps.back(); | |||
| 37341 | for ( auto& info : statInfo ) | |||
| 37342 | { | |||
| 37343 | for ( auto& currentInfo : lvlUp.statUps ) | |||
| 37344 | { | |||
| 37345 | if ( currentInfo.whichStat == info.whichStat ) | |||
| 37346 | { | |||
| 37347 | if ( info.increaseStat > 0 ) // ignore negatives | |||
| 37348 | { | |||
| 37349 | currentInfo.increaseStat += info.increaseStat; | |||
| 37350 | } | |||
| 37351 | } | |||
| 37352 | } | |||
| 37353 | } | |||
| 37354 | } | |||
| 37355 | else | |||
| 37356 | { | |||
| 37357 | bool inProgress = !lvlUps.empty(); | |||
| 37358 | lvlUps.push_back(LevelUp_t(currentLvl, increaseLvl)); | |||
| 37359 | auto& lvlUp = lvlUps.back(); | |||
| 37360 | if ( inProgress ) | |||
| 37361 | { | |||
| 37362 | // skip some animation | |||
| 37363 | lvlUp.titleFinishAnim = true; | |||
| 37364 | lvlUp.animTitleFade = 1.0; | |||
| 37365 | lvlUp.ticksToLive = 3 * TICKS_PER_SECOND50; | |||
| 37366 | } | |||
| 37367 | else | |||
| 37368 | { | |||
| 37369 | for ( int i = 0; i < MAXPLAYERS4; ++i ) | |||
| 37370 | { | |||
| 37371 | if ( &levelUpAnimation[i] == this ) | |||
| 37372 | { | |||
| 37373 | if ( levelupSoundDelay == 0 || ((ticks - levelupSoundDelay) > (TICKS_PER_SECOND50 / 10)) ) | |||
| 37374 | { | |||
| 37375 | playSoundNotificationPlayer(i, *cvar_lvlup_sfx, 255); | |||
| 37376 | levelupSoundDelay = TICKS_PER_SECOND50 / 10; | |||
| 37377 | } | |||
| 37378 | break; | |||
| 37379 | } | |||
| 37380 | } | |||
| 37381 | levelupSoundDelay = ticks; | |||
| 37382 | } | |||
| 37383 | ||||
| 37384 | for ( int i = 0; i < NUMSTATS; ++i ) | |||
| 37385 | { | |||
| 37386 | for ( auto& statUp : statInfo ) | |||
| 37387 | { | |||
| 37388 | if ( statUp.whichStat == i ) | |||
| 37389 | { | |||
| 37390 | lvlUp.statUps.push_back(statUp); | |||
| 37391 | } | |||
| 37392 | } | |||
| 37393 | } | |||
| 37394 | } | |||
| 37395 | } | |||
| 37396 | ||||
| 37397 | void LevelUpAnimation_t::LevelUp_t::StatUp_t::setAnimatePosition(int destx, int desty, int destw, int desth) | |||
| 37398 | { | |||
| 37399 | animateStartX = pos.x; | |||
| 37400 | animateStartY = pos.y; | |||
| 37401 | animateStartW = pos.w; | |||
| 37402 | animateStartH = pos.h; | |||
| 37403 | animateSetpointX = destx; | |||
| 37404 | animateSetpointY = desty; | |||
| 37405 | animateSetpointW = destw; | |||
| 37406 | animateSetpointH = desth; | |||
| 37407 | animateX = 0.0; | |||
| 37408 | animateY = 0.0; | |||
| 37409 | animateW = 0.0; | |||
| 37410 | animateH = 0.0; | |||
| 37411 | } | |||
| 37412 | ||||
| 37413 | void LevelUpAnimation_t::LevelUp_t::StatUp_t::setAnimatePosition(int destx, int desty) | |||
| 37414 | { | |||
| 37415 | animateStartX = pos.x; | |||
| 37416 | animateStartY = pos.y; | |||
| 37417 | animateStartW = pos.w; | |||
| 37418 | animateStartH = pos.h; | |||
| 37419 | animateSetpointX = destx; | |||
| 37420 | animateSetpointY = desty; | |||
| 37421 | animateSetpointW = 0; | |||
| 37422 | animateSetpointH = 0; | |||
| 37423 | animateX = 0.0; | |||
| 37424 | animateY = 0.0; | |||
| 37425 | animateW = 0.0; | |||
| 37426 | animateH = 0.0; | |||
| 37427 | } | |||
| 37428 | ||||
| 37429 | static ConsoleVariable<int> cvar_skill_ding_sfx("/skill_sfx_ding", 554); | |||
| 37430 | static ConsoleVariable<int> cvar_lvl_ding_sfx("/lvl_sfx_ding", 555); | |||
| 37431 | static ConsoleVariable<int> cvar_skill_sfx_volume("/skill_sfx_volume", 128); | |||
| 37432 | static ConsoleVariable<int> cvar_skill_newspell_sfx("/skill_sfx_newspell", 560); | |||
| 37433 | ||||
| 37434 | bool SkillUpAnimation_t::soundIndexUsedForNotification(const int index) | |||
| 37435 | { | |||
| 37436 | if ( index == 0 ) { return false; } | |||
| 37437 | if ( index >= *cvar_skill_ding_sfx && index <= *cvar_skill_ding_sfx + 3 ) | |||
| 37438 | { | |||
| 37439 | return true; | |||
| 37440 | } | |||
| 37441 | else if ( index == CalloutRadialMenu::CALLOUT_SFX_NEGATIVE | |||
| 37442 | || index == CalloutRadialMenu::CALLOUT_SFX_NEUTRAL | |||
| 37443 | || index == CalloutRadialMenu::CALLOUT_SFX_POSITIVE ) | |||
| 37444 | { | |||
| 37445 | return true; | |||
| 37446 | } | |||
| 37447 | else if ( index == Message::CHAT_MESSAGE_SFX ) | |||
| 37448 | { | |||
| 37449 | return true; | |||
| 37450 | } | |||
| 37451 | else if ( index == *cvar_lvl_ding_sfx ) | |||
| 37452 | { | |||
| 37453 | return true; | |||
| 37454 | } | |||
| 37455 | else if ( index == *cvar_skill_newspell_sfx ) | |||
| 37456 | { | |||
| 37457 | return true; | |||
| 37458 | } | |||
| 37459 | else | |||
| 37460 | { | |||
| 37461 | for ( auto skill : Player::SkillSheet_t::skillSheetData.skillEntries ) | |||
| 37462 | { | |||
| 37463 | if ( index == skill.skillSfx ) | |||
| 37464 | { | |||
| 37465 | return true; | |||
| 37466 | } | |||
| 37467 | } | |||
| 37468 | } | |||
| 37469 | return false; | |||
| 37470 | } | |||
| 37471 | ||||
| 37472 | void LevelUpAnimation_t::LevelUp_t::StatUp_t::animateNotification(const int player) | |||
| 37473 | { | |||
| 37474 | real_t animspeed = 5.0 / (4.0); | |||
| 37475 | static ConsoleVariable<float> cvar_lvlup_speed("/lvlup_speed", .5); | |||
| 37476 | static ConsoleVariable<float> cvar_lvlup_bounce("/lvlup_bounce", 1.0 /*2.5*/); | |||
| 37477 | static ConsoleVariable<float> cvar_lvlup_animfall("/lvlup_animfall", 0.5/*2.0*/); | |||
| 37478 | static ConsoleVariable<int> cvar_lvlup_ding_volume("/lvlup_ding_volume", 64); | |||
| 37479 | animspeed *= *cvar_lvlup_speed; | |||
| 37480 | int movementAmount = 0; | |||
| 37481 | if ( players[player]->bUseCompactGUIHeight() ) | |||
| 37482 | { | |||
| 37483 | movementAmount = 0; | |||
| 37484 | } | |||
| 37485 | ||||
| 37486 | if ( ticks != processedOnTick ) | |||
| 37487 | { | |||
| 37488 | processedOnTick = ticks; | |||
| 37489 | ++ticksActive; | |||
| 37490 | } | |||
| 37491 | ||||
| 37492 | const real_t largestScaling = 2.0; | |||
| 37493 | real_t midScaling = 2.0; | |||
| 37494 | const int normalSize = 36; | |||
| 37495 | const int baseEffectPosX = baseX; | |||
| 37496 | const int baseEffectPosY = baseY; | |||
| 37497 | ||||
| 37498 | switch ( notificationState ) | |||
| 37499 | { | |||
| 37500 | case STATE_1: | |||
| 37501 | if ( notificationStateInit == STATE_1 ) | |||
| 37502 | { | |||
| 37503 | notificationStateInit = STATE_2; | |||
| 37504 | setAnimatePosition( | |||
| 37505 | baseEffectPosX - movementAmount, | |||
| 37506 | baseEffectPosY - movementAmount, | |||
| 37507 | normalSize, normalSize); | |||
| 37508 | } | |||
| 37509 | if ( animateX >= 1.0 ) | |||
| 37510 | { | |||
| 37511 | notificationState = STATE_2; | |||
| 37512 | } | |||
| 37513 | animspeed *= .01; | |||
| 37514 | break; | |||
| 37515 | case STATE_2: | |||
| 37516 | if ( notificationStateInit == STATE_2 ) | |||
| 37517 | { | |||
| 37518 | notificationStateInit = STATE_3; | |||
| 37519 | setAnimatePosition( | |||
| 37520 | baseEffectPosX - movementAmount - (largestScaling - 1.0) * normalSize / 2, | |||
| 37521 | baseEffectPosY - movementAmount - (largestScaling - 1.0) * normalSize / 2, | |||
| 37522 | normalSize * largestScaling, | |||
| 37523 | normalSize * largestScaling); | |||
| 37524 | } | |||
| 37525 | if ( animateX >= 1.0 ) | |||
| 37526 | { | |||
| 37527 | notificationState = STATE_3; | |||
| 37528 | } | |||
| 37529 | animspeed *= 4.0; | |||
| 37530 | break; | |||
| 37531 | case STATE_3: | |||
| 37532 | if ( notificationStateInit == STATE_3 ) | |||
| 37533 | { | |||
| 37534 | midScaling = 1.0; | |||
| 37535 | notificationStateInit = STATE_4; | |||
| 37536 | setAnimatePosition( | |||
| 37537 | baseEffectPosX - movementAmount - (midScaling - 1.0) * normalSize / 2, | |||
| 37538 | baseEffectPosY - movementAmount - (midScaling - 1.0) * normalSize / 2, | |||
| 37539 | normalSize * midScaling, | |||
| 37540 | normalSize * midScaling); | |||
| 37541 | } | |||
| 37542 | if ( animateX >= 1.0 ) | |||
| 37543 | { | |||
| 37544 | notificationState = STATE_4; | |||
| 37545 | } | |||
| 37546 | animspeed *= 4.0; | |||
| 37547 | break; | |||
| 37548 | case STATE_4: | |||
| 37549 | if ( notificationStateInit == STATE_4 ) | |||
| 37550 | { | |||
| 37551 | notificationStateInit = STATE_END; | |||
| 37552 | setAnimatePosition(notificationTargetPosition.x, | |||
| 37553 | notificationTargetPosition.y, | |||
| 37554 | notificationTargetPosition.w, | |||
| 37555 | notificationTargetPosition.h); | |||
| 37556 | } | |||
| 37557 | if ( notificationTargetPosition.x != animateSetpointX | |||
| 37558 | || notificationTargetPosition.y != animateSetpointY | |||
| 37559 | || notificationTargetPosition.w != animateSetpointW | |||
| 37560 | || notificationTargetPosition.h != animateSetpointH ) | |||
| 37561 | { | |||
| 37562 | // re update this as our target moved. | |||
| 37563 | setAnimatePosition(notificationTargetPosition.x, | |||
| 37564 | notificationTargetPosition.y, | |||
| 37565 | notificationTargetPosition.w, | |||
| 37566 | notificationTargetPosition.h); | |||
| 37567 | } | |||
| 37568 | if ( animateX >= 1.0 ) | |||
| 37569 | { | |||
| 37570 | notificationState = STATE_END; | |||
| 37571 | } | |||
| 37572 | animspeed *= 2.0; | |||
| 37573 | break; | |||
| 37574 | case STATE_END: | |||
| 37575 | { | |||
| 37576 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 37577 | if ( ticksActive >= TICKS_PER_SECOND50 ) | |||
| 37578 | { | |||
| 37579 | real_t setpointDiffX = fpsScale * std::max(.1, (1.0 - animCurrentStat)) / (2.5 * *cvar_lvlup_animfall); | |||
| 37580 | animCurrentStat += setpointDiffX; | |||
| 37581 | animCurrentStat = std::min(1.0, animCurrentStat); | |||
| 37582 | ||||
| 37583 | if ( animCurrentStat >= 1.0 ) | |||
| 37584 | { | |||
| 37585 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 37586 | real_t setpointDiffX = fpsScale * 1.0 / (10.0 * *cvar_lvlup_bounce); | |||
| 37587 | animIncreaseStat += setpointDiffX; | |||
| 37588 | animIncreaseStat = std::min(1.0, animIncreaseStat); | |||
| 37589 | } | |||
| 37590 | } | |||
| 37591 | return; | |||
| 37592 | } | |||
| 37593 | default: | |||
| 37594 | break; | |||
| 37595 | } | |||
| 37596 | ||||
| 37597 | real_t oldAngle = animAngle; | |||
| 37598 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 37599 | animAngle += fpsScale * std::max(.1, (1.0 - animAngle)) / (5.0); | |||
| 37600 | animAngle = std::min(1.0, animAngle); | |||
| 37601 | if ( animAngle > 0.0 && oldAngle <= 0.001 ) | |||
| 37602 | { | |||
| 37603 | playSound(*cvar_lvl_ding_sfx, *cvar_lvlup_ding_volume); | |||
| 37604 | } | |||
| 37605 | real_t setpointDiffX = fpsScale * std::max(.1, (1.0 - animateX)) / (animspeed); | |||
| 37606 | real_t setpointDiffY = fpsScale * std::max(.1, (1.0 - animateY)) / (animspeed); | |||
| 37607 | real_t setpointDiffW = fpsScale * std::max(.1, (1.0 - animateW)) / (animspeed); | |||
| 37608 | real_t setpointDiffH = fpsScale * std::max(.1, (1.0 - animateH)) / (animspeed); | |||
| 37609 | animateX += setpointDiffX; | |||
| 37610 | animateY += setpointDiffY; | |||
| 37611 | animateX = std::min(1.0, animateX); | |||
| 37612 | animateY = std::min(1.0, animateY); | |||
| 37613 | animateW += setpointDiffW; | |||
| 37614 | animateH += setpointDiffH; | |||
| 37615 | animateW = std::min(1.0, animateW); | |||
| 37616 | animateH = std::min(1.0, animateH); | |||
| 37617 | ||||
| 37618 | int destX = animateSetpointX - animateStartX; | |||
| 37619 | int destY = animateSetpointY - animateStartY; | |||
| 37620 | int destW = animateSetpointW - animateStartW; | |||
| 37621 | int destH = animateSetpointH - animateStartH; | |||
| 37622 | ||||
| 37623 | pos.x = animateStartX + destX * animateX; | |||
| 37624 | pos.y = animateStartY + destY * animateY; | |||
| 37625 | pos.w = animateStartW + destW * animateW; | |||
| 37626 | pos.h = animateStartH + destH * animateH; | |||
| 37627 | } | |||
| 37628 | ||||
| 37629 | void LevelUpAnimation_t::LevelUp_t::animateTitle(SDL_Rect basePos) | |||
| 37630 | { | |||
| 37631 | if ( ticksActive == 0 ) | |||
| 37632 | { | |||
| 37633 | titleAnimatePos = basePos; | |||
| 37634 | } | |||
| 37635 | ||||
| 37636 | static ConsoleVariable<int> cvar_lvlup_title_ticks("/lvlup_title_ticks", 15); | |||
| 37637 | static ConsoleVariable<int> cvar_lvlup_title_fade_ticks("/lvlup_title_fade_ticks", TICKS_PER_SECOND50); | |||
| 37638 | real_t anim = std::min(1.0, ticksActive / (real_t)*cvar_lvlup_title_ticks); | |||
| 37639 | real_t grow = 1.0; | |||
| 37640 | ||||
| 37641 | real_t curvePosition = (LevelUpAnimBreakpoints[anim * (LevelUpAnimBreakpoints.size() - 1)]) / 100.0; | |||
| 37642 | ||||
| 37643 | //titleAnimatePos.x = basePos.x - anim * (grow) * basePos.w / 2; | |||
| 37644 | //titleAnimatePos.y = basePos.y - anim * (grow) * basePos.h / 2; | |||
| 37645 | //titleAnimatePos.w = basePos.w + anim * grow * basePos.w; | |||
| 37646 | //titleAnimatePos.h = basePos.h + anim * grow * basePos.h; | |||
| 37647 | titleAnimatePos.x = basePos.x - curvePosition * basePos.w / 2; | |||
| 37648 | titleAnimatePos.y = basePos.y - curvePosition * basePos.h / 2; | |||
| 37649 | titleAnimatePos.w = basePos.w + curvePosition * basePos.w; | |||
| 37650 | titleAnimatePos.h = basePos.h + curvePosition * basePos.h; | |||
| 37651 | ||||
| 37652 | if ( ticksActive >= *cvar_lvlup_title_fade_ticks ) | |||
| 37653 | { | |||
| 37654 | titleFinishAnim = true; | |||
| 37655 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 37656 | animTitleFade += fpsScale * std::max(.1, (1.0 - animTitleFade)) / (5.0); | |||
| 37657 | animTitleFade = std::min(1.0, animTitleFade); | |||
| 37658 | ||||
| 37659 | titleAnimatePos.y += animTitleFade * titleAnimatePos.h; | |||
| 37660 | } | |||
| 37661 | } | |||
| 37662 | ||||
| 37663 | void updateLevelUpFrame(const int player) | |||
| 37664 | { | |||
| 37665 | auto& hud_t = players[player]->hud; | |||
| 37666 | if ( !hud_t.levelupFrame ) | |||
| 37667 | { | |||
| 37668 | createLevelUpFrame(player); | |||
| 37669 | } | |||
| 37670 | ||||
| 37671 | if ( !hud_t.levelupFrame || !hud_t.hudFrame ) | |||
| 37672 | { | |||
| 37673 | return; | |||
| 37674 | } | |||
| 37675 | ||||
| 37676 | if ( !players[player]->isLocalPlayer() || hud_t.hudFrame->isDisabled() ) | |||
| 37677 | { | |||
| 37678 | hud_t.levelupFrame->setDisabled(true); | |||
| 37679 | return; | |||
| 37680 | } | |||
| 37681 | ||||
| 37682 | if ( gamePaused && multiplayer == SINGLE0 ) | |||
| 37683 | { | |||
| 37684 | return; | |||
| 37685 | } | |||
| 37686 | ||||
| 37687 | auto frame = hud_t.levelupFrame; | |||
| 37688 | auto& lvlUpAnimation = levelUpAnimation[player]; | |||
| 37689 | ||||
| 37690 | static ConsoleVariable<int> cvar_lvlup_debug("/lvlup_debug", 0); | |||
| 37691 | if ( *cvar_lvlup_debug > 0 ) | |||
| 37692 | { | |||
| 37693 | std::vector<int> statPicks; | |||
| 37694 | std::vector<unsigned int> statWeight = { 1, 1, 1, 1, 1, 1 }; | |||
| 37695 | if ( *cvar_lvlup_debug != 1 ) | |||
| 37696 | { | |||
| 37697 | for ( int i = 0; i < std::min(*cvar_lvlup_debug, NUMSTATS); ++i ) | |||
| 37698 | { | |||
| 37699 | int stat = local_rng.discrete(statWeight.data(), statWeight.size()); | |||
| 37700 | statWeight[stat] = 0; | |||
| 37701 | statPicks.push_back(stat); | |||
| 37702 | } | |||
| 37703 | } | |||
| 37704 | else | |||
| 37705 | { | |||
| 37706 | for ( int i = 0; i < 3; ++i ) | |||
| 37707 | { | |||
| 37708 | int stat = local_rng.discrete(statWeight.data(), statWeight.size()); | |||
| 37709 | statWeight[stat] = 0; | |||
| 37710 | statPicks.push_back(stat); | |||
| 37711 | } | |||
| 37712 | } | |||
| 37713 | int currentStat = 0; | |||
| 37714 | int increaseStat = 1; | |||
| 37715 | std::vector<LevelUpAnimation_t::LevelUp_t::StatUp_t> StatUps; | |||
| 37716 | for ( int i = 0; i < statPicks.size(); ++i ) | |||
| 37717 | { | |||
| 37718 | if ( *cvar_lvlup_debug != 1 ) | |||
| 37719 | { | |||
| 37720 | increaseStat = local_rng.rand() % 2; | |||
| 37721 | } | |||
| 37722 | switch ( statPicks[i] ) | |||
| 37723 | { | |||
| 37724 | case STAT_STR: | |||
| 37725 | currentStat = stats[player]->STR; | |||
| 37726 | break; | |||
| 37727 | case STAT_DEX: | |||
| 37728 | currentStat = stats[player]->DEX; | |||
| 37729 | break; | |||
| 37730 | case STAT_CON: | |||
| 37731 | currentStat = stats[player]->CON; | |||
| 37732 | break; | |||
| 37733 | case STAT_INT: | |||
| 37734 | currentStat = stats[player]->INT; | |||
| 37735 | break; | |||
| 37736 | case STAT_PER: | |||
| 37737 | currentStat = stats[player]->PER; | |||
| 37738 | break; | |||
| 37739 | case STAT_CHR: | |||
| 37740 | currentStat = stats[player]->CHR; | |||
| 37741 | break; | |||
| 37742 | default: | |||
| 37743 | break; | |||
| 37744 | } | |||
| 37745 | ||||
| 37746 | StatUps.push_back(LevelUpAnimation_t::LevelUp_t::StatUp_t(statPicks[i], currentStat, increaseStat)); | |||
| 37747 | } | |||
| 37748 | ||||
| 37749 | /*lvlUpAnimation.lvlUps.clear();*/ | |||
| 37750 | lvlUpAnimation.addLevelUp(stats[player]->LVL, 1, StatUps); | |||
| 37751 | ||||
| 37752 | for ( auto& lvlUp : lvlUpAnimation.lvlUps ) | |||
| 37753 | { | |||
| 37754 | messagePlayer(player, MESSAGE_DEBUG, "Lvl: [%d %d]", lvlUp.currentLvl, lvlUp.increaseLvl); | |||
| 37755 | for ( auto& statUp : lvlUp.statUps ) | |||
| 37756 | { | |||
| 37757 | messagePlayer(player, MESSAGE_DEBUG, "Stat: %d: [%d %d]", statUp.whichStat, statUp.currentStat, statUp.increaseStat); | |||
| 37758 | } | |||
| 37759 | } | |||
| 37760 | *cvar_lvlup_debug = 0; | |||
| 37761 | } | |||
| 37762 | ||||
| 37763 | if ( lvlUpAnimation.lvlUps.empty() ) | |||
| 37764 | { | |||
| 37765 | hud_t.levelupFrame->setDisabled(true); | |||
| 37766 | return; | |||
| 37767 | } | |||
| 37768 | ||||
| 37769 | if ( lvlUpAnimation.lvlUps.front().expired ) | |||
| 37770 | { | |||
| 37771 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 37772 | lvlUpAnimation.lvlUps.front().fadeout += fpsScale * std::max(.1, (1.0 - lvlUpAnimation.lvlUps.front().fadeout)) / (5.0); | |||
| 37773 | lvlUpAnimation.lvlUps.front().fadeout = std::min(1.0, lvlUpAnimation.lvlUps.front().fadeout); | |||
| 37774 | hud_t.levelupFrame->setOpacity(hud_t.hudFrame->getOpacity() | |||
| 37775 | * (1.0 - lvlUpAnimation.lvlUps.front().fadeout)); | |||
| 37776 | if ( lvlUpAnimation.lvlUps.front().fadeout >= 1.0 ) | |||
| 37777 | { | |||
| 37778 | lvlUpAnimation.lvlUps.pop_front(); | |||
| 37779 | } | |||
| 37780 | } | |||
| 37781 | ||||
| 37782 | if ( lvlUpAnimation.lvlUps.empty() ) | |||
| 37783 | { | |||
| 37784 | hud_t.levelupFrame->setDisabled(true); | |||
| 37785 | return; | |||
| 37786 | } | |||
| 37787 | ||||
| 37788 | auto& lvlUp = lvlUpAnimation.lvlUps.front(); | |||
| 37789 | ||||
| 37790 | static ConsoleVariable<int> cvar_lvlup_angle("/lvlup_angle", 16); | |||
| 37791 | static ConsoleVariable<int> cvar_lvlup_falldist("/lvlup_falldist", 64); | |||
| 37792 | static ConsoleVariable<int> cvar_lvlup_currentstatY("/lvlup_currentstatY", -10); | |||
| 37793 | static ConsoleVariable<int> cvar_lvlup_increasestatY("/lvlup_increasestatY", 0); | |||
| 37794 | ||||
| 37795 | if ( !lvlUp.expired ) | |||
| 37796 | { | |||
| 37797 | hud_t.levelupFrame->setOpacity(hud_t.hudFrame->getOpacity()); | |||
| 37798 | } | |||
| 37799 | hud_t.levelupFrame->setDisabled(false); | |||
| 37800 | const int frameWidth = 600; | |||
| 37801 | ||||
| 37802 | ||||
| 37803 | auto lvlupImg = hud_t.levelupFrame->findImage("lvl up img"); | |||
| 37804 | lvlupImg->disabled = false; | |||
| 37805 | if ( auto imgGet = Image::get(lvlupImg->path.c_str()) ) | |||
| 37806 | { | |||
| 37807 | lvlupImg->pos.w = imgGet->getWidth(); | |||
| 37808 | lvlupImg->pos.h = imgGet->getHeight(); | |||
| 37809 | lvlupImg->pos.x = frameWidth / 2 - lvlupImg->pos.w / 2; | |||
| 37810 | lvlupImg->pos.y = 0; | |||
| 37811 | } | |||
| 37812 | ||||
| 37813 | SDL_Rect statsFramePos{ frameWidth / 2, 0, 0, 200 }; | |||
| 37814 | auto statsFrame = hud_t.levelupFrame->findFrame("stats"); | |||
| 37815 | statsFrame->setDisabled(true); | |||
| 37816 | ||||
| 37817 | lvlUp.animateTitle(lvlupImg->pos); | |||
| 37818 | lvlupImg->pos = lvlUp.titleAnimatePos; | |||
| 37819 | lvlupImg->color = makeColor(255, 255, 255, 255 * (1.0 - lvlUp.animTitleFade)); | |||
| 37820 | if ( lvlUp.titleFinishAnim ) | |||
| 37821 | { | |||
| 37822 | statsFrame->setDisabled(false); | |||
| 37823 | } | |||
| 37824 | ||||
| 37825 | int index = 0; | |||
| 37826 | SDL_Rect statFramePos{ 0, 0, 0, 200 }; | |||
| 37827 | const int statSpacing = 64; | |||
| 37828 | int statStartX = 100; | |||
| 37829 | std::vector<int> statPosX; | |||
| 37830 | auto prevNotificationState = LevelUpAnimation_t::LevelUp_t::StatUp_t::NotificationStates_t::STATE_END; | |||
| 37831 | for ( auto statFrame : statsFrame->getFrames() ) | |||
| 37832 | { | |||
| 37833 | if ( statsFrame->isDisabled() ) | |||
| 37834 | { | |||
| 37835 | statFrame->setDisabled(true); | |||
| 37836 | continue; | |||
| 37837 | } | |||
| 37838 | int currentIndex = index; | |||
| 37839 | ++index; | |||
| 37840 | if ( currentIndex >= lvlUp.statUps.size() ) | |||
| 37841 | { | |||
| 37842 | statFrame->setDisabled(true); | |||
| 37843 | continue; | |||
| 37844 | } | |||
| 37845 | auto& statUp = lvlUp.statUps[currentIndex]; | |||
| 37846 | auto statImg = statFrame->findImage("stat img"); | |||
| 37847 | statImg->path = ""; | |||
| 37848 | statImg->disabled = true; | |||
| 37849 | switch ( statUp.whichStat ) | |||
| 37850 | { | |||
| 37851 | case STAT_STR: | |||
| 37852 | //statImg->path = Player::CharacterSheet_t::getHoverTextString("icon_str_path"); | |||
| 37853 | statImg->path = "images/ui/HUD/HUD_StatUp_STR_00.png"; | |||
| 37854 | break; | |||
| 37855 | case STAT_DEX: | |||
| 37856 | statImg->path = "images/ui/HUD/HUD_StatUp_DEX_00.png"; | |||
| 37857 | break; | |||
| 37858 | case STAT_CON: | |||
| 37859 | statImg->path = "images/ui/HUD/HUD_StatUp_CON_00.png"; | |||
| 37860 | break; | |||
| 37861 | case STAT_INT: | |||
| 37862 | statImg->path = "images/ui/HUD/HUD_StatUp_INT_00.png"; | |||
| 37863 | break; | |||
| 37864 | case STAT_PER: | |||
| 37865 | statImg->path = "images/ui/HUD/HUD_StatUp_PER_00.png"; | |||
| 37866 | break; | |||
| 37867 | case STAT_CHR: | |||
| 37868 | statImg->path = "images/ui/HUD/HUD_StatUp_CHA_00.png"; | |||
| 37869 | break; | |||
| 37870 | default: | |||
| 37871 | break; | |||
| 37872 | } | |||
| 37873 | ||||
| 37874 | char buf[32] = ""; | |||
| 37875 | ||||
| 37876 | if ( statImg->path == "" ) { continue; } | |||
| 37877 | ||||
| 37878 | if ( auto imgGet = Image::get(statImg->path.c_str()) ) | |||
| 37879 | { | |||
| 37880 | statImg->pos.w = imgGet->getWidth(); | |||
| 37881 | statImg->pos.h = imgGet->getHeight(); | |||
| 37882 | statImg->disabled = false; | |||
| 37883 | } | |||
| 37884 | statImg->pos.x = 32; | |||
| 37885 | int baseImgY = 48; | |||
| 37886 | if ( players[player]->bUseCompactGUIHeight() ) | |||
| 37887 | { | |||
| 37888 | baseImgY = 40; | |||
| 37889 | } | |||
| 37890 | statImg->pos.y = baseImgY - statImg->pos.h / 2; | |||
| 37891 | ||||
| 37892 | snprintf(buf, sizeof(buf), "%+d", statUp.increaseStat); | |||
| 37893 | auto statIncreaseTxt = statFrame->findField("stat increase"); | |||
| 37894 | statIncreaseTxt->setDisabled(statUp.increaseStat == 0); | |||
| 37895 | statIncreaseTxt->setText(buf); | |||
| 37896 | if ( auto textGet = statIncreaseTxt->getTextObject() ) | |||
| 37897 | { | |||
| 37898 | SDL_Rect pos; | |||
| 37899 | pos.x = statImg->pos.x + statImg->pos.w + 8; | |||
| 37900 | pos.y = baseImgY - 8; | |||
| 37901 | pos.w = std::max(40, (int)textGet->getWidth()); | |||
| 37902 | pos.h = std::max(24, (int)textGet->getHeight()); | |||
| 37903 | ||||
| 37904 | statIncreaseTxt->setColor(makeColor(255, 255, 255, (1.0 - statUp.animCurrentStat) * statUp.animAngle * 255)); | |||
| 37905 | pos.x += -*cvar_lvlup_angle * cos(PI3.14159265358979323846 / 2 + (3 * statUp.animAngle * (PI3.14159265358979323846 / 2))); | |||
| 37906 | pos.y += (*cvar_lvlup_angle) - (*cvar_lvlup_angle * sin(PI3.14159265358979323846 / 2 + (3 * statUp.animAngle * (PI3.14159265358979323846 / 2)))); | |||
| 37907 | pos.y += *cvar_lvlup_increasestatY; | |||
| 37908 | statIncreaseTxt->setSize(pos); | |||
| 37909 | } | |||
| 37910 | ||||
| 37911 | snprintf(buf, sizeof(buf), "%d", statUp.currentStat + statUp.increaseStat); | |||
| 37912 | auto statCurrentTxt = statFrame->findField("stat current"); | |||
| 37913 | statCurrentTxt->setDisabled(!(statUp.ticksActive >= TICKS_PER_SECOND50 * 1)); | |||
| 37914 | statCurrentTxt->setText(buf); | |||
| 37915 | if ( auto textGet = statCurrentTxt->getTextObject() ) | |||
| 37916 | { | |||
| 37917 | SDL_Rect pos; | |||
| 37918 | pos.w = textGet->getWidth(); | |||
| 37919 | pos.h = textGet->getHeight(); | |||
| 37920 | pos.x = statImg->pos.x + statImg->pos.w / 2 - pos.w / 2; | |||
| 37921 | pos.y = statImg->pos.y + statImg->pos.h + 4; | |||
| 37922 | pos.y += *cvar_lvlup_currentstatY; | |||
| 37923 | if ( statUp.increaseStat != 0 ) | |||
| 37924 | { | |||
| 37925 | pos.y += -((1.0 - statUp.animCurrentStat) * *cvar_lvlup_falldist); | |||
| 37926 | pos.y += -4 + 4 * (cos(statUp.animIncreaseStat * 2 * PI3.14159265358979323846)); | |||
| 37927 | } | |||
| 37928 | statCurrentTxt->setSize(pos); | |||
| 37929 | ||||
| 37930 | Uint8 r, g, b, a; | |||
| 37931 | getColor(0xFFFFFFFF, &r, &g, &b, &a); | |||
| 37932 | statCurrentTxt->setColor(makeColor(r, g, b, statUp.animCurrentStat * a)); | |||
| 37933 | } | |||
| 37934 | ||||
| 37935 | statFramePos.w = 120; | |||
| 37936 | statFrame->setSize(statFramePos); | |||
| 37937 | ||||
| 37938 | statPosX.push_back(statFramePos.x + statImg->pos.x + statImg->pos.w / 2); | |||
| 37939 | statFramePos.x += statSpacing; | |||
| 37940 | ||||
| 37941 | if ( !statUp.init && (prevNotificationState == LevelUpAnimation_t::LevelUp_t::StatUp_t::NotificationStates_t::STATE_END | |||
| 37942 | || prevNotificationState >= LevelUpAnimation_t::LevelUp_t::StatUp_t::NotificationStates_t::STATE_3) ) | |||
| 37943 | { | |||
| 37944 | statUp.notificationTargetPosition.x = statImg->pos.x; | |||
| 37945 | statUp.notificationTargetPosition.y = statImg->pos.y; | |||
| 37946 | statUp.notificationTargetPosition.w = statImg->pos.w; | |||
| 37947 | statUp.notificationTargetPosition.h = statImg->pos.h; | |||
| 37948 | statUp.baseX = statImg->pos.x; | |||
| 37949 | statUp.baseY = statImg->pos.y; | |||
| 37950 | statUp.pos.x = statUp.baseX; | |||
| 37951 | statUp.pos.y = statUp.baseY; | |||
| 37952 | statUp.pos.w = statImg->pos.w; | |||
| 37953 | statUp.pos.h = statImg->pos.h; | |||
| 37954 | statUp.init = true; | |||
| 37955 | } | |||
| 37956 | ||||
| 37957 | if ( statUp.init ) | |||
| 37958 | { | |||
| 37959 | statUp.animateNotification(player); | |||
| 37960 | statFrame->setDisabled(false); | |||
| 37961 | } | |||
| 37962 | else | |||
| 37963 | { | |||
| 37964 | statFrame->setDisabled(true); | |||
| 37965 | } | |||
| 37966 | statImg->pos = statUp.pos; | |||
| 37967 | statsFramePos.w = statFramePos.x + statFramePos.w; | |||
| 37968 | statStartX += statSpacing; | |||
| 37969 | ||||
| 37970 | prevNotificationState = statUp.notificationState; | |||
| 37971 | } | |||
| 37972 | ||||
| 37973 | int midpoint = 0; | |||
| 37974 | if ( statPosX.size() > 1 ) | |||
| 37975 | { | |||
| 37976 | if ( statPosX.size() % 2 == 1 ) | |||
| 37977 | { | |||
| 37978 | midpoint = statPosX[size_t(statPosX.size() / 2)]; | |||
| 37979 | } | |||
| 37980 | else | |||
| 37981 | { | |||
| 37982 | size_t midIndex1 = std::max((size_t)0, (statPosX.size() / 2) - 1); | |||
| 37983 | size_t midIndex2 = (statPosX.size() / 2); | |||
| 37984 | midpoint = statPosX[midIndex1] + (statPosX[midIndex2] - statPosX[midIndex1]) / 2; | |||
| 37985 | } | |||
| 37986 | statsFramePos.x -= midpoint; | |||
| 37987 | } | |||
| 37988 | else if ( statPosX.size() == 1 ) | |||
| 37989 | { | |||
| 37990 | statsFramePos.x -= statPosX[0]; | |||
| 37991 | } | |||
| 37992 | else | |||
| 37993 | { | |||
| 37994 | statsFramePos.x -= statsFramePos.w / 2; | |||
| 37995 | } | |||
| 37996 | if ( statsFramePos.x % 2 == 1 ) | |||
| 37997 | { | |||
| 37998 | ++statsFramePos.x; | |||
| 37999 | } | |||
| 38000 | statsFrame->setSize(statsFramePos); | |||
| 38001 | if ( ticks != lvlUp.processedOnTick ) | |||
| 38002 | { | |||
| 38003 | lvlUp.processedOnTick = ticks; | |||
| 38004 | ++lvlUp.ticksActive; | |||
| 38005 | } | |||
| 38006 | ||||
| 38007 | static ConsoleVariable<int> cvar_lvlup_framey("/lvlup_framey", 16); | |||
| 38008 | SDL_Rect levelUpFramePos{ hud_t.hudFrame->getSize().w / 2 - frameWidth / 2, *cvar_lvlup_framey, | |||
| 38009 | frameWidth, std::max(lvlupImg->pos.y + lvlupImg->pos.h, statsFramePos.y + statsFramePos.h)}; | |||
| 38010 | levelUpFramePos.x += players[player]->camera_virtualx1(); | |||
| 38011 | levelUpFramePos.y += players[player]->camera_virtualy1(); | |||
| 38012 | levelUpFramePos.y += lvlUp.fadeout * *cvar_lvlup_falldist; | |||
| 38013 | hud_t.levelupFrame->setSize(levelUpFramePos); | |||
| 38014 | ||||
| 38015 | if ( lvlUp.ticksActive >= lvlUp.ticksToLive ) | |||
| 38016 | { | |||
| 38017 | lvlUp.expired = true; | |||
| 38018 | } | |||
| 38019 | } | |||
| 38020 | ||||
| 38021 | SkillUpAnimation_t skillUpAnimation[MAXPLAYERS4]; | |||
| 38022 | ||||
| 38023 | void createSkillUpFrame(const int player) | |||
| 38024 | { | |||
| 38025 | auto& hud_t = players[player]->hud; | |||
| 38026 | hud_t.skillupFrame = gameUIFrame[player]->addFrame("skillup"); | |||
| 38027 | hud_t.skillupFrame->setHollow(true); | |||
| 38028 | hud_t.skillupFrame->setInheritParentFrameOpacity(false); | |||
| 38029 | hud_t.skillupFrame->setOpacity(100.0); | |||
| 38030 | hud_t.skillupFrame->setDisabled(true); | |||
| 38031 | hud_t.skillupFrame->setOwner(player); | |||
| 38032 | ||||
| 38033 | auto skillsFrame = hud_t.skillupFrame->addFrame("skills"); | |||
| 38034 | skillsFrame->setDisabled(true); | |||
| 38035 | skillsFrame->setHollow(true); | |||
| 38036 | char name[32]; | |||
| 38037 | std::string font = "fonts/pixelmix.ttf#16#2"; | |||
| 38038 | ||||
| 38039 | auto skillFrame = skillsFrame->addFrame("skill"); | |||
| 38040 | skillFrame->setDisabled(true); | |||
| 38041 | skillFrame->setHollow(true); | |||
| 38042 | ||||
| 38043 | skillFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "skill bg img"); | |||
| 38044 | skillFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "skill bg cap img"); | |||
| 38045 | skillFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "skill border img"); | |||
| 38046 | skillFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "skill img"); | |||
| 38047 | skillFrame->addImage(SDL_Rect{ 0, 0, 0, 0 }, 0xFFFFFFFF, "", "skill gleam"); | |||
| 38048 | ||||
| 38049 | auto skillCurrentTxt = skillFrame->addField("skill current", 32); | |||
| 38050 | skillCurrentTxt->setFont(font.c_str()); | |||
| 38051 | skillCurrentTxt->setHJustify(Field::justify_t::RIGHT); | |||
| 38052 | skillCurrentTxt->setVJustify(Field::justify_t::TOP); | |||
| 38053 | skillCurrentTxt->setText("0"); | |||
| 38054 | ||||
| 38055 | auto skillCurrentOldTxt = skillFrame->addField("skill current old", 32); | |||
| 38056 | skillCurrentOldTxt->setFont(font.c_str()); | |||
| 38057 | skillCurrentOldTxt->setHJustify(Field::justify_t::RIGHT); | |||
| 38058 | skillCurrentOldTxt->setVJustify(Field::justify_t::TOP); | |||
| 38059 | skillCurrentOldTxt->setText("0"); | |||
| 38060 | ||||
| 38061 | auto skillIncreaseTxt = skillFrame->addField("skill increase", 32); | |||
| 38062 | skillIncreaseTxt->setFont(font.c_str()); | |||
| 38063 | skillIncreaseTxt->setHJustify(Field::justify_t::LEFT); | |||
| 38064 | skillIncreaseTxt->setVJustify(Field::justify_t::TOP); | |||
| 38065 | skillIncreaseTxt->setText("0"); | |||
| 38066 | ||||
| 38067 | std::string font2 = "fonts/pixel_maz.ttf#32#2"; | |||
| 38068 | auto skillNameTxt = skillFrame->addField("skill name txt", 64); | |||
| 38069 | skillNameTxt->setFont(font2.c_str()); | |||
| 38070 | skillNameTxt->setHJustify(Field::justify_t::RIGHT); | |||
| 38071 | skillNameTxt->setVJustify(Field::justify_t::TOP); | |||
| 38072 | skillNameTxt->setText(""); | |||
| 38073 | } | |||
| 38074 | ||||
| 38075 | void SkillUpAnimation_t::SkillUp_t::setAnimatePosition(int destx, int desty, int destw, int desth) | |||
| 38076 | { | |||
| 38077 | animateStartX = pos.x; | |||
| 38078 | animateStartY = pos.y; | |||
| 38079 | animateStartW = pos.w; | |||
| 38080 | animateStartH = pos.h; | |||
| 38081 | animateSetpointX = destx; | |||
| 38082 | animateSetpointY = desty; | |||
| 38083 | animateSetpointW = destw; | |||
| 38084 | animateSetpointH = desth; | |||
| 38085 | animateX = 0.0; | |||
| 38086 | animateY = 0.0; | |||
| 38087 | animateW = 0.0; | |||
| 38088 | animateH = 0.0; | |||
| 38089 | } | |||
| 38090 | ||||
| 38091 | void SkillUpAnimation_t::SkillUp_t::setAnimatePosition(int destx, int desty) | |||
| 38092 | { | |||
| 38093 | animateStartX = pos.x; | |||
| 38094 | animateStartY = pos.y; | |||
| 38095 | animateStartW = pos.w; | |||
| 38096 | animateStartH = pos.h; | |||
| 38097 | animateSetpointX = destx; | |||
| 38098 | animateSetpointY = desty; | |||
| 38099 | animateSetpointW = 0; | |||
| 38100 | animateSetpointH = 0; | |||
| 38101 | animateX = 0.0; | |||
| 38102 | animateY = 0.0; | |||
| 38103 | animateW = 0.0; | |||
| 38104 | animateH = 0.0; | |||
| 38105 | } | |||
| 38106 | ||||
| 38107 | int SkillUpAnimation_t::SkillUp_t::getIconNominalSize() | |||
| 38108 | { | |||
| 38109 | return isSpell ? 32 : 24; | |||
| 38110 | } | |||
| 38111 | ||||
| 38112 | void SkillUpAnimation_t::SkillUp_t::animateNotification(const int player) | |||
| 38113 | { | |||
| 38114 | real_t animspeed = 5.0 / (4.0); | |||
| 38115 | static ConsoleVariable<float> cvar_skillup_speed("/skillup_speed", .5); | |||
| 38116 | static ConsoleVariable<float> cvar_skillup_bounce("/skillup_bounce", 1.0 /*2.5*/); | |||
| 38117 | static ConsoleVariable<float> cvar_skillup_animfall("/skillup_animfall", 0.5/*2.0*/); | |||
| 38118 | static ConsoleVariable<int> cvar_skillup_increase_delay("/skillup_increase_delay", 50); | |||
| 38119 | static ConsoleVariable<int> cvar_skillup_ding_volume("/skillup_ding_volume", 32); | |||
| 38120 | animspeed *= *cvar_skillup_speed; | |||
| 38121 | int movementAmount = 0; | |||
| 38122 | if ( players[player]->bUseCompactGUIHeight() ) | |||
| 38123 | { | |||
| 38124 | movementAmount = 0; | |||
| 38125 | } | |||
| 38126 | ||||
| 38127 | bool newtick = ticks != processedOnTick; | |||
| 38128 | if ( newtick ) | |||
| 38129 | { | |||
| 38130 | processedOnTick = ticks; | |||
| 38131 | ++ticksActive; | |||
| 38132 | } | |||
| 38133 | ||||
| 38134 | const real_t largestScaling = 2.0; | |||
| 38135 | real_t midScaling = 2.0; | |||
| 38136 | const int normalSize = getIconNominalSize(); | |||
| 38137 | const int baseEffectPosX = baseX; | |||
| 38138 | const int baseEffectPosY = baseY; | |||
| 38139 | ||||
| 38140 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 38141 | if ( notificationState >= STATE_4 ) | |||
| 38142 | { | |||
| 38143 | real_t setpointDiffX = fpsScale * std::max(.1, (1.0 - animBackground)) / (2.5); | |||
| 38144 | animBackground += setpointDiffX; | |||
| 38145 | animBackground = std::min(1.0, animBackground); | |||
| 38146 | } | |||
| 38147 | ||||
| 38148 | real_t oldAngle = animAngle; | |||
| 38149 | animAngle += fpsScale * std::max(.1, (1.0 - animAngle)) / (5.0); | |||
| 38150 | animAngle = std::min(1.0, animAngle); | |||
| 38151 | if ( newtick && ticksActive == *cvar_skillup_increase_delay ) | |||
| 38152 | { | |||
| 38153 | if ( !isSpell ) | |||
| 38154 | { | |||
| 38155 | playSound(*cvar_skill_ding_sfx + local_rng.rand() % 4, *cvar_skillup_ding_volume); | |||
| 38156 | } | |||
| 38157 | } | |||
| 38158 | ||||
| 38159 | switch ( notificationState ) | |||
| 38160 | { | |||
| 38161 | case STATE_1: | |||
| 38162 | if ( notificationStateInit == STATE_1 ) | |||
| 38163 | { | |||
| 38164 | notificationStateInit = STATE_2; | |||
| 38165 | setAnimatePosition( | |||
| 38166 | baseEffectPosX - movementAmount, | |||
| 38167 | baseEffectPosY - movementAmount, | |||
| 38168 | normalSize, normalSize); | |||
| 38169 | } | |||
| 38170 | if ( animateX >= 1.0 ) | |||
| 38171 | { | |||
| 38172 | notificationState = STATE_2; | |||
| 38173 | } | |||
| 38174 | animspeed *= .01; | |||
| 38175 | break; | |||
| 38176 | case STATE_2: | |||
| 38177 | if ( notificationStateInit == STATE_2 ) | |||
| 38178 | { | |||
| 38179 | notificationStateInit = STATE_3; | |||
| 38180 | setAnimatePosition( | |||
| 38181 | baseEffectPosX - movementAmount - (largestScaling - 1.0) * normalSize / 2, | |||
| 38182 | baseEffectPosY - movementAmount - (largestScaling - 1.0) * normalSize / 2, | |||
| 38183 | normalSize * largestScaling, | |||
| 38184 | normalSize * largestScaling); | |||
| 38185 | } | |||
| 38186 | if ( animateX >= 1.0 ) | |||
| 38187 | { | |||
| 38188 | notificationState = STATE_3; | |||
| 38189 | } | |||
| 38190 | animspeed *= 4.0; | |||
| 38191 | break; | |||
| 38192 | case STATE_3: | |||
| 38193 | if ( notificationStateInit == STATE_3 ) | |||
| 38194 | { | |||
| 38195 | midScaling = 1.0; | |||
| 38196 | notificationStateInit = STATE_4; | |||
| 38197 | setAnimatePosition( | |||
| 38198 | baseEffectPosX - movementAmount - (midScaling - 1.0) * normalSize / 2, | |||
| 38199 | baseEffectPosY - movementAmount - (midScaling - 1.0) * normalSize / 2, | |||
| 38200 | normalSize * midScaling, | |||
| 38201 | normalSize * midScaling); | |||
| 38202 | } | |||
| 38203 | if ( animateX >= 1.0 ) | |||
| 38204 | { | |||
| 38205 | notificationState = STATE_4; | |||
| 38206 | } | |||
| 38207 | animspeed *= 4.0; | |||
| 38208 | break; | |||
| 38209 | case STATE_4: | |||
| 38210 | if ( notificationStateInit == STATE_4 ) | |||
| 38211 | { | |||
| 38212 | notificationStateInit = STATE_END; | |||
| 38213 | setAnimatePosition(notificationTargetPosition.x, | |||
| 38214 | notificationTargetPosition.y, | |||
| 38215 | notificationTargetPosition.w, | |||
| 38216 | notificationTargetPosition.h); | |||
| 38217 | } | |||
| 38218 | if ( notificationTargetPosition.x != animateSetpointX | |||
| 38219 | || notificationTargetPosition.y != animateSetpointY | |||
| 38220 | || notificationTargetPosition.w != animateSetpointW | |||
| 38221 | || notificationTargetPosition.h != animateSetpointH ) | |||
| 38222 | { | |||
| 38223 | // re update this as our target moved. | |||
| 38224 | setAnimatePosition(notificationTargetPosition.x, | |||
| 38225 | notificationTargetPosition.y, | |||
| 38226 | notificationTargetPosition.w, | |||
| 38227 | notificationTargetPosition.h); | |||
| 38228 | } | |||
| 38229 | if ( animateX >= 1.0 ) | |||
| 38230 | { | |||
| 38231 | notificationState = STATE_END; | |||
| 38232 | } | |||
| 38233 | animspeed *= 2.0; | |||
| 38234 | break; | |||
| 38235 | case STATE_END: | |||
| 38236 | { | |||
| 38237 | if ( ticksActive >= TICKS_PER_SECOND50 ) | |||
| 38238 | { | |||
| 38239 | real_t setpointDiffX = fpsScale * std::max(.1, (1.0 - animCurrentStat)) / (2.5 * *cvar_skillup_animfall); | |||
| 38240 | animCurrentStat += setpointDiffX; | |||
| 38241 | animCurrentStat = std::min(1.0, animCurrentStat); | |||
| 38242 | ||||
| 38243 | if ( animCurrentStat >= 1.0 ) | |||
| 38244 | { | |||
| 38245 | real_t setpointDiffX = fpsScale * 1.0 / (10.0 * *cvar_skillup_bounce); | |||
| 38246 | animIncreaseStat += setpointDiffX; | |||
| 38247 | animIncreaseStat = std::min(1.0, animIncreaseStat); | |||
| 38248 | } | |||
| 38249 | } | |||
| 38250 | return; | |||
| 38251 | } | |||
| 38252 | default: | |||
| 38253 | break; | |||
| 38254 | } | |||
| 38255 | ||||
| 38256 | real_t setpointDiffX = fpsScale * std::max(.1, (1.0 - animateX)) / (animspeed); | |||
| 38257 | real_t setpointDiffY = fpsScale * std::max(.1, (1.0 - animateY)) / (animspeed); | |||
| 38258 | real_t setpointDiffW = fpsScale * std::max(.1, (1.0 - animateW)) / (animspeed); | |||
| 38259 | real_t setpointDiffH = fpsScale * std::max(.1, (1.0 - animateH)) / (animspeed); | |||
| 38260 | animateX += setpointDiffX; | |||
| 38261 | animateY += setpointDiffY; | |||
| 38262 | animateX = std::min(1.0, animateX); | |||
| 38263 | animateY = std::min(1.0, animateY); | |||
| 38264 | animateW += setpointDiffW; | |||
| 38265 | animateH += setpointDiffH; | |||
| 38266 | animateW = std::min(1.0, animateW); | |||
| 38267 | animateH = std::min(1.0, animateH); | |||
| 38268 | ||||
| 38269 | int destX = animateSetpointX - animateStartX; | |||
| 38270 | int destY = animateSetpointY - animateStartY; | |||
| 38271 | int destW = animateSetpointW - animateStartW; | |||
| 38272 | int destH = animateSetpointH - animateStartH; | |||
| 38273 | ||||
| 38274 | pos.x = animateStartX + destX * animateX; | |||
| 38275 | pos.y = animateStartY + destY * animateY; | |||
| 38276 | pos.w = animateStartW + destW * animateW; | |||
| 38277 | pos.h = animateStartH + destH * animateH; | |||
| 38278 | } | |||
| 38279 | ||||
| 38280 | SkillUpAnimation_t::SkillUp_t& SkillUpAnimation_t::getSkillUpToDisplay() | |||
| 38281 | { | |||
| 38282 | return skillUps.at(getSkillUpIndexToDisplay()); | |||
| 38283 | } | |||
| 38284 | ||||
| 38285 | size_t SkillUpAnimation_t::getSkillUpIndexToDisplay() | |||
| 38286 | { | |||
| 38287 | size_t index = 0; | |||
| 38288 | std::priority_queue<std::pair<int, size_t>> priority; | |||
| 38289 | for ( auto& skillUp : skillUps ) | |||
| 38290 | { | |||
| 38291 | if ( skillUp.init ) | |||
| 38292 | { | |||
| 38293 | return index; | |||
| 38294 | } | |||
| 38295 | if ( skillUp.isSpell ) | |||
| 38296 | { | |||
| 38297 | priority.push(std::make_pair(15, index)); | |||
| 38298 | } | |||
| 38299 | else | |||
| 38300 | { | |||
| 38301 | switch ( skillUp.whichSkill ) | |||
| 38302 | { | |||
| 38303 | case PRO_RANGED: | |||
| 38304 | case PRO_SWORD: | |||
| 38305 | case PRO_MACE: | |||
| 38306 | case PRO_AXE: | |||
| 38307 | case PRO_POLEARM: | |||
| 38308 | case PRO_SHIELD: | |||
| 38309 | case PRO_UNARMED: | |||
| 38310 | priority.push(std::make_pair(10, index)); | |||
| 38311 | break; | |||
| 38312 | case PRO_MAGIC: | |||
| 38313 | case PRO_SPELLCASTING: | |||
| 38314 | priority.push(std::make_pair(5, index)); | |||
| 38315 | break; | |||
| 38316 | case PRO_STEALTH: | |||
| 38317 | priority.push(std::make_pair(4, index)); | |||
| 38318 | break; | |||
| 38319 | case PRO_LOCKPICKING: | |||
| 38320 | case PRO_TRADING: | |||
| 38321 | case PRO_LEADERSHIP: | |||
| 38322 | case PRO_ALCHEMY: | |||
| 38323 | priority.push(std::make_pair(2, index)); | |||
| 38324 | break; | |||
| 38325 | case PRO_SWIMMING: | |||
| 38326 | priority.push(std::make_pair(1, index)); | |||
| 38327 | break; | |||
| 38328 | case PRO_APPRAISAL: | |||
| 38329 | default: | |||
| 38330 | priority.push(std::make_pair(0, index)); | |||
| 38331 | break; | |||
| 38332 | } | |||
| 38333 | } | |||
| 38334 | ++index; | |||
| 38335 | } | |||
| 38336 | return priority.top().second; | |||
| 38337 | } | |||
| 38338 | ||||
| 38339 | void SkillUpAnimation_t::addSpellLearned(const int _spellID) | |||
| 38340 | { | |||
| 38341 | skillUps.push_back(SkillUp_t(_spellID)); | |||
| 38342 | skillUps.at(skillUps.size() - 1).ticksToLive = 5 * TICKS_PER_SECOND50; | |||
| 38343 | } | |||
| 38344 | ||||
| 38345 | void SkillUpAnimation_t::addSkillUp(const int _numSkill, const int _currentSkill, const int _increaseSkill) | |||
| 38346 | { | |||
| 38347 | if ( _increaseSkill <= 0 ) | |||
| 38348 | { | |||
| 38349 | return; | |||
| 38350 | } | |||
| 38351 | ||||
| 38352 | for ( auto& s : skillUps ) | |||
| 38353 | { | |||
| 38354 | if ( s.whichSkill != _numSkill ) | |||
| 38355 | { | |||
| 38356 | continue; | |||
| 38357 | } | |||
| 38358 | if ( s.expired ) | |||
| 38359 | { | |||
| 38360 | continue; | |||
| 38361 | } | |||
| 38362 | int diff = std::max(0, (_currentSkill + _increaseSkill) - (s.currentSkill + s.increaseSkill)); | |||
| 38363 | if ( diff > 0 ) | |||
| 38364 | { | |||
| 38365 | if ( s.ticksActive >= TICKS_PER_SECOND50 ) | |||
| 38366 | { | |||
| 38367 | // update current value | |||
| 38368 | s.currentSkill = _currentSkill; | |||
| 38369 | s.increaseSkill = _increaseSkill; | |||
| 38370 | } | |||
| 38371 | else | |||
| 38372 | { | |||
| 38373 | s.increaseSkill += diff; | |||
| 38374 | } | |||
| 38375 | s.ticksActive = 0; | |||
| 38376 | s.animAngle = 0.0; | |||
| 38377 | s.animCurrentStat = 0.0; | |||
| 38378 | s.animIncreaseStat = 0.0; | |||
| 38379 | return; | |||
| 38380 | } | |||
| 38381 | else | |||
| 38382 | { | |||
| 38383 | return; | |||
| 38384 | } | |||
| 38385 | } | |||
| 38386 | ||||
| 38387 | skillUps.push_back(SkillUp_t(_numSkill, _currentSkill, _increaseSkill)); | |||
| 38388 | Uint32 ticksToLive = 3 * TICKS_PER_SECOND50; | |||
| 38389 | switch ( _numSkill ) | |||
| 38390 | { | |||
| 38391 | case PRO_RANGED: | |||
| 38392 | case PRO_SWORD: | |||
| 38393 | case PRO_MACE: | |||
| 38394 | case PRO_AXE: | |||
| 38395 | case PRO_POLEARM: | |||
| 38396 | case PRO_SHIELD: | |||
| 38397 | case PRO_UNARMED: | |||
| 38398 | ticksToLive = 4 * TICKS_PER_SECOND50; | |||
| 38399 | break; | |||
| 38400 | case PRO_STEALTH: | |||
| 38401 | ticksToLive = 4 * TICKS_PER_SECOND50; | |||
| 38402 | break; | |||
| 38403 | case PRO_MAGIC: | |||
| 38404 | case PRO_SPELLCASTING: | |||
| 38405 | ticksToLive = 2 * TICKS_PER_SECOND50; | |||
| 38406 | break; | |||
| 38407 | case PRO_LOCKPICKING: | |||
| 38408 | case PRO_TRADING: | |||
| 38409 | case PRO_LEADERSHIP: | |||
| 38410 | case PRO_ALCHEMY: | |||
| 38411 | ticksToLive = 3 * TICKS_PER_SECOND50; | |||
| 38412 | break; | |||
| 38413 | case PRO_SWIMMING: | |||
| 38414 | ticksToLive = 2 * TICKS_PER_SECOND50; | |||
| 38415 | break; | |||
| 38416 | case PRO_APPRAISAL: | |||
| 38417 | default: | |||
| 38418 | ticksToLive = 2 * TICKS_PER_SECOND50; | |||
| 38419 | break; | |||
| 38420 | } | |||
| 38421 | skillUps.at(skillUps.size() - 1).ticksToLive = ticksToLive; | |||
| 38422 | } | |||
| 38423 | ||||
| 38424 | void updateSkillUpFrame(const int player) | |||
| 38425 | { | |||
| 38426 | auto& hud_t = players[player]->hud; | |||
| 38427 | if ( !hud_t.skillupFrame ) | |||
| 38428 | { | |||
| 38429 | createSkillUpFrame(player); | |||
| 38430 | } | |||
| 38431 | ||||
| 38432 | if ( !hud_t.skillupFrame || !hud_t.hudFrame ) | |||
| 38433 | { | |||
| 38434 | return; | |||
| 38435 | } | |||
| 38436 | ||||
| 38437 | if ( !players[player]->isLocalPlayer() || hud_t.hudFrame->isDisabled() ) | |||
| 38438 | { | |||
| 38439 | hud_t.skillupFrame->setDisabled(true); | |||
| 38440 | return; | |||
| 38441 | } | |||
| 38442 | ||||
| 38443 | if ( gamePaused && multiplayer == SINGLE0 ) | |||
| 38444 | { | |||
| 38445 | return; | |||
| 38446 | } | |||
| 38447 | ||||
| 38448 | auto frame = hud_t.skillupFrame; | |||
| 38449 | auto& skillUpAnim = skillUpAnimation[player]; | |||
| 38450 | ||||
| 38451 | //if ( enableDebugKeys && keystatus[SDLK_g] ) | |||
| 38452 | //{ | |||
| 38453 | // keystatus[SDLK_g] = 0; | |||
| 38454 | ||||
| 38455 | // int skill = PRO_APPRAISAL; local_rng.rand() % NUMPROFICIENCIES; | |||
| 38456 | // int currentSkill = stats[player]->PROFICIENCIES[skill]; | |||
| 38457 | // int increaseSkill = 1; | |||
| 38458 | // skillUpAnim.addSkillUp(skill, currentSkill, increaseSkill); | |||
| 38459 | // //skillUpAnim.skillUps.push_back(SkillUpAnimation_t::SkillUp_t(skill, currentSkill, increaseSkill)); | |||
| 38460 | // ++stats[player]->PROFICIENCIES[skill]; | |||
| 38461 | //} | |||
| 38462 | ||||
| 38463 | //if ( enableDebugKeys && keystatus[SDLK_h] ) | |||
| 38464 | //{ | |||
| 38465 | // keystatus[SDLK_h] = 0; | |||
| 38466 | ||||
| 38467 | // skillUpAnim.addSpellLearned(SPELL_FORCEBOLT + local_rng.rand() % (NUM_SPELLS - 1)); | |||
| 38468 | //} | |||
| 38469 | ||||
| 38470 | if ( skillUpAnim.skillUps.empty() || levelUpAnimation[player].lvlUps.size() > 0 ) | |||
| 38471 | { | |||
| 38472 | if ( levelUpAnimation[player].lvlUps.size() > 0 ) | |||
| 38473 | { | |||
| 38474 | skillUpAnim.animFrameFadeIn = 0.0; | |||
| 38475 | } | |||
| 38476 | hud_t.skillupFrame->setDisabled(true); | |||
| 38477 | return; | |||
| 38478 | } | |||
| 38479 | ||||
| 38480 | if ( players[player]->bUseCompactGUIWidth() && players[player]->gui_mode != GUI_MODE_NONE ) | |||
| 38481 | { | |||
| 38482 | hud_t.skillupFrame->setDisabled(true); | |||
| 38483 | return; | |||
| 38484 | } | |||
| 38485 | ||||
| 38486 | auto& skillUpCheck = skillUpAnim.getSkillUpToDisplay(); | |||
| 38487 | const real_t fpsScale = getFPSScale(50.0); // ported from 50Hz | |||
| 38488 | if ( skillUpCheck.expired ) | |||
| 38489 | { | |||
| 38490 | skillUpCheck.fadeout += fpsScale * std::max(.1, (1.0 - skillUpCheck.fadeout)) / (5.0); | |||
| 38491 | skillUpCheck.fadeout = std::min(1.0, skillUpCheck.fadeout); | |||
| 38492 | hud_t.skillupFrame->setOpacity(hud_t.hudFrame->getOpacity() | |||
| 38493 | * (1.0 - skillUpCheck.fadeout) * skillUpAnim.animFrameFadeIn); | |||
| 38494 | if ( skillUpCheck.fadeout >= 1.0 ) | |||
| 38495 | { | |||
| 38496 | skillUpAnim.skillUps.erase(skillUpAnim.skillUps.begin() + skillUpAnim.getSkillUpIndexToDisplay()); | |||
| 38497 | } | |||
| 38498 | } | |||
| 38499 | ||||
| 38500 | if ( skillUpAnim.skillUps.empty() ) | |||
| 38501 | { | |||
| 38502 | hud_t.skillupFrame->setDisabled(true); | |||
| 38503 | return; | |||
| 38504 | } | |||
| 38505 | ||||
| 38506 | auto& skillUp = skillUpAnim.getSkillUpToDisplay(); | |||
| 38507 | ||||
| 38508 | static ConsoleVariable<int> cvar_skillup_angle("/skillup_angle", 16); | |||
| 38509 | static ConsoleVariable<int> cvar_skillup_falldist("/skillup_falldist", 64); | |||
| 38510 | static ConsoleVariable<int> cvar_skillup_currentstatY("/skillup_currentstatY", -10); | |||
| 38511 | static ConsoleVariable<int> cvar_skillup_increasestatY("/skillup_increasestatY", 0); | |||
| 38512 | ||||
| 38513 | if ( !skillUp.expired ) | |||
| 38514 | { | |||
| 38515 | skillUpAnim.animFrameFadeIn += fpsScale * std::max(.1, (1.0 - skillUpAnim.animFrameFadeIn)) / (5.0); | |||
| 38516 | skillUpAnim.animFrameFadeIn = std::min(1.0, skillUpAnim.animFrameFadeIn); | |||
| 38517 | hud_t.skillupFrame->setOpacity(hud_t.hudFrame->getOpacity() * skillUpAnim.animFrameFadeIn); | |||
| 38518 | } | |||
| 38519 | hud_t.skillupFrame->setDisabled(false); | |||
| 38520 | const int frameWidth = 600; | |||
| 38521 | ||||
| 38522 | SDL_Rect skillsFramePos{ frameWidth / 2, 0, 0, 200 }; | |||
| 38523 | auto skillsFrame = hud_t.skillupFrame->findFrame("skills"); | |||
| 38524 | skillsFrame->setDisabled(false); | |||
| 38525 | ||||
| 38526 | int index = 0; | |||
| 38527 | SDL_Rect skillFramePos{ 0, 0, 0, 400 }; | |||
| 38528 | const int skillSpacing = 64; | |||
| 38529 | int skillStartX = 100; | |||
| 38530 | std::vector<int> skillPosX; | |||
| 38531 | auto prevNotificationState = SkillUpAnimation_t::SkillUp_t::NotificationStates_t::STATE_END; | |||
| 38532 | for ( auto skillFrame : skillsFrame->getFrames() ) | |||
| 38533 | { | |||
| 38534 | if ( skillsFrame->isDisabled() ) | |||
| 38535 | { | |||
| 38536 | skillFrame->setDisabled(true); | |||
| 38537 | continue; | |||
| 38538 | } | |||
| 38539 | if ( skillUp.preDelayTicks > 0 ) | |||
| 38540 | { | |||
| 38541 | continue; | |||
| 38542 | } | |||
| 38543 | auto skillImg = skillFrame->findImage("skill img"); | |||
| 38544 | auto skillBorderImg = skillFrame->findImage("skill border img"); | |||
| 38545 | auto skillBgImg = skillFrame->findImage("skill bg img"); | |||
| 38546 | auto skillBgCapImg = skillFrame->findImage("skill bg cap img"); | |||
| 38547 | skillBgCapImg->disabled = true; | |||
| 38548 | skillImg->path = ""; | |||
| 38549 | skillImg->disabled = true; | |||
| 38550 | skillBorderImg->disabled = true; | |||
| 38551 | skillBgImg->disabled = true; | |||
| 38552 | int skillsheetIndex = -1; | |||
| 38553 | auto skillCurrentTxt = skillFrame->findField("skill current"); | |||
| 38554 | auto skillCurrentOldTxt = skillFrame->findField("skill current old"); | |||
| 38555 | ||||
| 38556 | if ( skillUp.isSpell ) | |||
| 38557 | { | |||
| 38558 | skillCurrentTxt->setDisabled(true); | |||
| 38559 | } | |||
| 38560 | else | |||
| 38561 | { | |||
| 38562 | char buf[32] = ""; | |||
| 38563 | snprintf(buf, sizeof(buf), "%d", skillUp.currentSkill + skillUp.increaseSkill); | |||
| 38564 | skillCurrentTxt->setDisabled(!(skillUp.ticksActive >= TICKS_PER_SECOND50 * 1)); | |||
| 38565 | skillCurrentTxt->setText(buf); | |||
| 38566 | } | |||
| 38567 | ||||
| 38568 | if ( skillUp.isSpell ) | |||
| 38569 | { | |||
| 38570 | node_t* spellImageNode = ItemTooltips.getSpellNodeFromSpellID(skillUp.spellID); | |||
| 38571 | if ( spellImageNode ) | |||
| 38572 | { | |||
| 38573 | if ( string_t* string = (string_t*)spellImageNode->element ) | |||
| 38574 | { | |||
| 38575 | skillImg->path = string->data; | |||
| 38576 | } | |||
| 38577 | skillCurrentTxt->setColor(Player::SkillSheet_t::skillSheetData.defaultTextColor); | |||
| 38578 | skillCurrentOldTxt->setColor(hudColors.itemContextMenuHeadingText); | |||
| 38579 | skillBorderImg->path = "#*images/ui/HUD/HUD_NewSpell_Border_00.png"; | |||
| 38580 | skillBgImg->path = "*images/ui/HUD/HUD_NewSpell_BG_00.png"; | |||
| 38581 | } | |||
| 38582 | } | |||
| 38583 | else | |||
| 38584 | { | |||
| 38585 | for ( auto& skill : Player::SkillSheet_t::skillSheetData.skillEntries ) | |||
| 38586 | { | |||
| 38587 | ++skillsheetIndex; | |||
| 38588 | if ( skill.skillId == skillUp.whichSkill ) | |||
| 38589 | { | |||
| 38590 | skillImg->path = skill.skillIconPath; | |||
| 38591 | int currentskill = skillCurrentTxt->isDisabled() ? skillUp.currentSkill : skillUp.currentSkill + skillUp.increaseSkill; | |||
| 38592 | if ( currentskill >= SKILL_LEVEL_LEGENDARY ) | |||
| 38593 | { | |||
| 38594 | skillImg->path = skill.skillIconPathLegend; | |||
| 38595 | skillCurrentTxt->setColor(Player::SkillSheet_t::skillSheetData.legendTextColor); | |||
| 38596 | skillCurrentOldTxt->setColor(Player::SkillSheet_t::skillSheetData.legendTextColor); | |||
| 38597 | skillBorderImg->path = Player::SkillSheet_t::skillSheetData.iconBgPathLegend; | |||
| 38598 | skillBgImg->path = "*images/ui/HUD/HUD_SkillUp_BG100_00.png"; | |||
| 38599 | } | |||
| 38600 | else if ( currentskill >= SKILL_LEVEL_EXPERT ) | |||
| 38601 | { | |||
| 38602 | skillCurrentTxt->setColor(Player::SkillSheet_t::skillSheetData.expertTextColor); | |||
| 38603 | skillCurrentOldTxt->setColor(Player::SkillSheet_t::skillSheetData.expertTextColor); | |||
| 38604 | skillBorderImg->path = Player::SkillSheet_t::skillSheetData.iconBgPathExpert; | |||
| 38605 | skillBgImg->path = "*images/ui/HUD/HUD_SkillUp_BG60_00.png"; | |||
| 38606 | } | |||
| 38607 | else if ( currentskill >= SKILL_LEVEL_BASIC ) | |||
| 38608 | { | |||
| 38609 | skillCurrentTxt->setColor(Player::SkillSheet_t::skillSheetData.noviceTextColor); | |||
| 38610 | skillCurrentOldTxt->setColor(Player::SkillSheet_t::skillSheetData.noviceTextColor); | |||
| 38611 | skillBorderImg->path = Player::SkillSheet_t::skillSheetData.iconBgPathNovice; | |||
| 38612 | skillBgImg->path = "*images/ui/HUD/HUD_SkillUp_BG20_00.png"; | |||
| 38613 | } | |||
| 38614 | else | |||
| 38615 | { | |||
| 38616 | skillCurrentTxt->setColor(Player::SkillSheet_t::skillSheetData.defaultTextColor); | |||
| 38617 | skillCurrentOldTxt->setColor(Player::SkillSheet_t::skillSheetData.defaultTextColor); | |||
| 38618 | skillBorderImg->path = Player::SkillSheet_t::skillSheetData.iconBgPathDefault; | |||
| 38619 | skillBgImg->path = "*images/ui/HUD/HUD_SkillUp_BG_00.png"; | |||
| 38620 | } | |||
| 38621 | break; | |||
| 38622 | } | |||
| 38623 | } | |||
| 38624 | } | |||
| 38625 | ||||
| 38626 | if ( skillImg->path == "" ) { continue; } | |||
| 38627 | ||||
| 38628 | if ( auto imgGet = Image::get(skillImg->path.c_str()) ) | |||
| 38629 | { | |||
| 38630 | skillImg->pos.w = imgGet->getWidth(); | |||
| 38631 | skillImg->pos.h = imgGet->getHeight(); | |||
| 38632 | skillImg->disabled = false; | |||
| 38633 | } | |||
| 38634 | skillImg->pos.x = 140; | |||
| 38635 | if ( !skillUp.isSpell ) | |||
| 38636 | { | |||
| 38637 | skillImg->pos.y = 40 - skillImg->pos.h / 2; | |||
| 38638 | } | |||
| 38639 | else | |||
| 38640 | { | |||
| 38641 | skillImg->pos.y = 44 - skillImg->pos.h / 2; | |||
| 38642 | } | |||
| 38643 | ||||
| 38644 | if ( auto imgGet = Image::get(skillBorderImg->path.c_str()) ) | |||
| 38645 | { | |||
| 38646 | skillBorderImg->pos.w = imgGet->getWidth(); | |||
| 38647 | skillBorderImg->pos.h = imgGet->getHeight(); | |||
| 38648 | skillBorderImg->disabled = false; | |||
| 38649 | skillBorderImg->pos.x = skillImg->pos.x + skillImg->pos.w / 2 - skillBorderImg->pos.w / 2; | |||
| 38650 | skillBorderImg->pos.y = skillImg->pos.y + skillImg->pos.h / 2 - skillBorderImg->pos.h / 2; | |||
| 38651 | } | |||
| 38652 | ||||
| 38653 | auto skillIncreaseTxt = skillFrame->findField("skill increase"); | |||
| 38654 | skillIncreaseTxt->setDisabled(skillUp.increaseSkill == 0 || skillUp.isSpell); | |||
| 38655 | if ( !skillIncreaseTxt->isDisabled() ) | |||
| 38656 | { | |||
| 38657 | char buf[32] = ""; | |||
| 38658 | snprintf(buf, sizeof(buf), "%+d", skillUp.increaseSkill); | |||
| 38659 | skillIncreaseTxt->setText(buf); | |||
| 38660 | if ( auto textGet = skillIncreaseTxt->getTextObject() ) | |||
| 38661 | { | |||
| 38662 | SDL_Rect pos; | |||
| 38663 | pos.x = skillImg->pos.x + skillImg->pos.w + 8; | |||
| 38664 | pos.y = 32; | |||
| 38665 | pos.w = std::max(40, (int)textGet->getWidth()); | |||
| 38666 | pos.h = std::max(24, (int)textGet->getHeight()); | |||
| 38667 | ||||
| 38668 | skillIncreaseTxt->setColor(makeColor(255, 255, 255, (1.0 - skillUp.animCurrentStat) * skillUp.animAngle * 255)); | |||
| 38669 | pos.x += -*cvar_skillup_angle * cos(PI3.14159265358979323846 / 2 + (3 * skillUp.animAngle * (PI3.14159265358979323846 / 2))); | |||
| 38670 | pos.x += (skillBgImg->pos.w - skillBorderImg->pos.w) * skillUp.animBackground; | |||
| 38671 | pos.y += (*cvar_skillup_angle) - (*cvar_skillup_angle * sin(PI3.14159265358979323846 / 2 + (3 * skillUp.animAngle * (PI3.14159265358979323846 / 2)))); | |||
| 38672 | pos.y += *cvar_skillup_increasestatY; | |||
| 38673 | skillIncreaseTxt->setSize(pos); | |||
| 38674 | } | |||
| 38675 | } | |||
| 38676 | ||||
| 38677 | if ( skillUp.isSpell ) | |||
| 38678 | { | |||
| 38679 | if ( auto spell = getSpellFromID(skillUp.spellID) ) | |||
| 38680 | { | |||
| 38681 | std::string spellname = spell->getSpellName(); | |||
| 38682 | camelCaseString(spellname); | |||
| 38683 | skillCurrentOldTxt->setText(spellname.c_str()); | |||
| 38684 | } | |||
| 38685 | } | |||
| 38686 | ||||
| 38687 | if ( auto imgGet = Image::get(skillBgImg->path.c_str()) ) | |||
| 38688 | { | |||
| 38689 | skillBgImg->color = makeColor(255, 255, 255, skillUp.animBackground * 255); | |||
| 38690 | skillBgImg->pos.w = imgGet->getWidth(); | |||
| 38691 | skillBgImg->pos.h = imgGet->getHeight(); | |||
| 38692 | skillBgImg->disabled = false; | |||
| 38693 | skillBgImg->pos.y = skillBorderImg->pos.y; | |||
| 38694 | if ( skillUp.isSpell ) | |||
| 38695 | { | |||
| 38696 | skillBgCapImg->path = "#*images/ui/HUD/HUD_NewSpell_BG_Cap_00.png"; | |||
| 38697 | if ( auto imgGet2 = Image::get(skillBgCapImg->path.c_str()) ) | |||
| 38698 | { | |||
| 38699 | skillBgCapImg->disabled = false; | |||
| 38700 | skillBgCapImg->pos.w = imgGet2->getWidth(); | |||
| 38701 | skillBgCapImg->pos.h = imgGet2->getHeight(); | |||
| 38702 | skillBgCapImg->pos.y = skillBgImg->pos.y; | |||
| 38703 | skillBgCapImg->color = skillBgImg->color; | |||
| 38704 | } | |||
| 38705 | if ( auto textGet = skillCurrentOldTxt->getTextObject() ) | |||
| 38706 | { | |||
| 38707 | skillBgImg->pos.w = (textGet->getWidth() + 8 + skillBgCapImg->pos.w) * skillUp.animBackground; | |||
| 38708 | if ( skillBgImg->pos.w == 0 ) | |||
| 38709 | { | |||
| 38710 | skillBgImg->disabled = true; | |||
| 38711 | } | |||
| 38712 | int bgStartX = skillBorderImg->pos.x + skillBorderImg->pos.w - skillBgCapImg->pos.w; | |||
| 38713 | skillBgImg->pos.x = bgStartX; | |||
| 38714 | skillBgCapImg->pos.x = skillBgImg->pos.x + skillBgImg->pos.w; | |||
| 38715 | } | |||
| 38716 | } | |||
| 38717 | else | |||
| 38718 | { | |||
| 38719 | skillBgImg->pos.x = skillBorderImg->pos.x - skillBorderImg->pos.w + skillBorderImg->pos.w * skillUp.animBackground; | |||
| 38720 | } | |||
| 38721 | } | |||
| 38722 | ||||
| 38723 | auto skillGleam = skillFrame->findImage("skill gleam"); | |||
| 38724 | skillGleam->disabled = !skillUp.isSpell; | |||
| 38725 | ||||
| 38726 | skillCurrentOldTxt->setDisabled(true); | |||
| 38727 | if ( skillCurrentTxt->isDisabled() ) | |||
| 38728 | { | |||
| 38729 | skillCurrentOldTxt->setDisabled(false); | |||
| 38730 | ||||
| 38731 | if ( !skillUp.isSpell ) | |||
| 38732 | { | |||
| 38733 | char buf[32] = ""; | |||
| 38734 | snprintf(buf, sizeof(buf), "%d", skillUp.currentSkill); | |||
| 38735 | skillCurrentOldTxt->setText(buf); | |||
| 38736 | } | |||
| 38737 | if ( auto textGet = skillCurrentOldTxt->getTextObject() ) | |||
| 38738 | { | |||
| 38739 | SDL_Rect pos; | |||
| 38740 | pos.w = textGet->getWidth(); | |||
| 38741 | pos.h = std::max(24, (int)textGet->getHeight()); | |||
| 38742 | if ( skillUp.isSpell ) | |||
| 38743 | { | |||
| 38744 | pos.w = std::min(pos.w, skillBgImg->pos.w); | |||
| 38745 | pos.y = skillBgImg->pos.y + 12; | |||
| 38746 | skillCurrentOldTxt->setFont("fonts/pixel_maz_multiline.ttf#16#2"); | |||
| 38747 | pos.x = skillBgCapImg->pos.x - pos.w; | |||
| 38748 | } | |||
| 38749 | else | |||
| 38750 | { | |||
| 38751 | pos.x = skillBgImg->pos.x + skillBgImg->pos.w - pos.w - 12; | |||
| 38752 | pos.y = skillBgImg->pos.y + 8; | |||
| 38753 | skillCurrentOldTxt->setFont("fonts/pixelmix.ttf#16#2"); | |||
| 38754 | } | |||
| 38755 | skillCurrentOldTxt->setSize(pos); | |||
| 38756 | ||||
| 38757 | Uint8 r, g, b, a; | |||
| 38758 | getColor(skillCurrentOldTxt->getColor(), &r, &g, &b, &a); | |||
| 38759 | skillCurrentOldTxt->setColor(makeColor(r, g, b, skillUp.animBackground * a)); | |||
| 38760 | } | |||
| 38761 | } | |||
| 38762 | else if ( auto textGet = skillCurrentTxt->getTextObject() ) | |||
| 38763 | { | |||
| 38764 | SDL_Rect pos; | |||
| 38765 | pos.w = textGet->getWidth(); | |||
| 38766 | pos.h = textGet->getHeight(); | |||
| 38767 | pos.x = skillBgImg->pos.x + skillBgImg->pos.w - pos.w - 12; | |||
| 38768 | pos.y = skillBgImg->pos.y + 8; | |||
| 38769 | ||||
| 38770 | if ( skillUp.increaseSkill != 0 ) | |||
| 38771 | { | |||
| 38772 | pos.y += -((1.0 - skillUp.animCurrentStat) * *cvar_skillup_falldist); | |||
| 38773 | pos.y += -4 + 4 * (cos(skillUp.animIncreaseStat * 2 * PI3.14159265358979323846)); | |||
| 38774 | } | |||
| 38775 | skillCurrentTxt->setSize(pos); | |||
| 38776 | ||||
| 38777 | Uint8 r, g, b, a; | |||
| 38778 | getColor(skillCurrentTxt->getColor(), &r, &g, &b, &a); | |||
| 38779 | skillCurrentTxt->setColor(makeColor(r, g, b, skillUp.animCurrentStat * a)); | |||
| 38780 | } | |||
| 38781 | ||||
| 38782 | skillFramePos.w = std::max(120, (int)(skillBgImg->pos.x + skillBgImg->pos.w + 64)); | |||
| 38783 | if ( skillUp.isSpell ) | |||
| 38784 | { | |||
| 38785 | skillFramePos.w = std::max(skillFramePos.w, (skillBgCapImg->pos.x + skillBgCapImg->pos.w)); | |||
| 38786 | } | |||
| 38787 | skillFrame->setSize(skillFramePos); | |||
| 38788 | ||||
| 38789 | if ( skillUp.isSpell ) | |||
| 38790 | { | |||
| 38791 | skillPosX.push_back(skillFramePos.x + skillImg->pos.x + skillImg->pos.w / 2 + ((skillBgImg->pos.w) /** skillUp.animBackground*/ / 2)); | |||
| 38792 | } | |||
| 38793 | else | |||
| 38794 | { | |||
| 38795 | skillPosX.push_back(skillFramePos.x + skillImg->pos.x + skillImg->pos.w / 2 + ((skillBgImg->pos.w - skillBorderImg->pos.w) * skillUp.animBackground / 2)); | |||
| 38796 | } | |||
| 38797 | ||||
| 38798 | auto skillNameTxt = skillFrame->findField("skill name txt"); | |||
| 38799 | skillNameTxt->setDisabled(true); | |||
| 38800 | { | |||
| 38801 | if ( skillUp.isSpell ) | |||
| 38802 | { | |||
| 38803 | skillNameTxt->setText(Language::get(4328)); | |||
| 38804 | } | |||
| 38805 | else | |||
| 38806 | { | |||
| 38807 | char buf[128]; | |||
| 38808 | snprintf(buf, sizeof(buf), Language::get(4327), Player::SkillSheet_t::skillSheetData.skillEntries[skillsheetIndex].name.c_str()); | |||
| 38809 | skillNameTxt->setText(buf); | |||
| 38810 | } | |||
| 38811 | if ( auto textGet = skillNameTxt->getTextObject() ) | |||
| 38812 | { | |||
| 38813 | skillNameTxt->setDisabled(false); | |||
| 38814 | SDL_Rect pos = skillNameTxt->getSize(); | |||
| 38815 | pos.w = textGet->getWidth(); | |||
| 38816 | pos.h = std::max(24, (int)textGet->getHeight()); | |||
| 38817 | pos.y = 0; | |||
| 38818 | pos.x = skillPosX[skillPosX.size() - 1] - pos.w / 2; | |||
| 38819 | skillNameTxt->setSize(pos); | |||
| 38820 | ||||
| 38821 | Uint8 r, g, b, a; | |||
| 38822 | getColor(0xFFFFFFFF, &r, &g, &b, &a); | |||
| 38823 | skillNameTxt->setColor(makeColor(r, g, b, skillUp.animBackground * a)); | |||
| 38824 | ||||
| 38825 | skillFramePos.w = std::max(skillFramePos.w, (int)(pos.x + pos.w)); | |||
| 38826 | skillFrame->setSize(skillFramePos); | |||
| 38827 | } | |||
| 38828 | } | |||
| 38829 | ||||
| 38830 | skillFramePos.x += skillSpacing; | |||
| 38831 | ||||
| 38832 | if ( !skillUp.init ) | |||
| 38833 | { | |||
| 38834 | skillUp.notificationTargetPosition.x = skillImg->pos.x; | |||
| 38835 | skillUp.notificationTargetPosition.y = skillImg->pos.y; | |||
| 38836 | skillUp.notificationTargetPosition.w = skillImg->pos.w; | |||
| 38837 | skillUp.notificationTargetPosition.h = skillImg->pos.h; | |||
| 38838 | skillUp.baseX = skillImg->pos.x; | |||
| 38839 | skillUp.baseY = skillImg->pos.y; | |||
| 38840 | skillUp.pos.x = skillUp.baseX; | |||
| 38841 | skillUp.pos.y = skillUp.baseY; | |||
| 38842 | skillUp.pos.w = skillImg->pos.w; | |||
| 38843 | skillUp.pos.h = skillImg->pos.h; | |||
| 38844 | skillUp.init = true; | |||
| 38845 | ||||
| 38846 | if ( skillUp.isSpell ) | |||
| 38847 | { | |||
| 38848 | playSound(*cvar_skill_newspell_sfx, *cvar_skill_sfx_volume); | |||
| 38849 | } | |||
| 38850 | else | |||
| 38851 | { | |||
| 38852 | for ( auto skill : Player::SkillSheet_t::skillSheetData.skillEntries ) | |||
| 38853 | { | |||
| 38854 | if ( skill.skillId == skillUp.whichSkill ) | |||
| 38855 | { | |||
| 38856 | playSound(skill.skillSfx, *cvar_skill_sfx_volume); | |||
| 38857 | break; | |||
| 38858 | } | |||
| 38859 | } | |||
| 38860 | } | |||
| 38861 | } | |||
| 38862 | ||||
| 38863 | if ( skillUp.init ) | |||
| 38864 | { | |||
| 38865 | skillUp.animateNotification(player); | |||
| 38866 | skillFrame->setDisabled(false); | |||
| 38867 | } | |||
| 38868 | else | |||
| 38869 | { | |||
| 38870 | skillFrame->setDisabled(true); | |||
| 38871 | } | |||
| 38872 | skillImg->pos = skillUp.pos; | |||
| 38873 | { | |||
| 38874 | int newWidth = skillBorderImg->pos.w * (skillImg->pos.w / (float)skillUp.getIconNominalSize()); | |||
| 38875 | int newHeight = skillBorderImg->pos.h * (skillImg->pos.h / (float)skillUp.getIconNominalSize()); | |||
| 38876 | skillBorderImg->pos.x -= (newWidth - skillBorderImg->pos.w) / 2; | |||
| 38877 | skillBorderImg->pos.y -= (newHeight - skillBorderImg->pos.h) / 2; | |||
| 38878 | skillBorderImg->pos.w = newWidth; | |||
| 38879 | skillBorderImg->pos.h = newHeight; | |||
| 38880 | ||||
| 38881 | if ( skillUp.isSpell ) | |||
| 38882 | { | |||
| 38883 | skillGleam->path = "*#images/ui/HUD/HUD_NewSpell_Gleam_00.png"; | |||
| 38884 | skillGleam->pos = skillBorderImg->pos; | |||
| 38885 | const int gleam = ((ticks % TICKS_PER_SECOND50) / 5) % 5; | |||
| 38886 | switch ( gleam ) | |||
| 38887 | { | |||
| 38888 | case 0: | |||
| 38889 | skillGleam->path = "*#images/ui/HUD/HUD_NewSpell_Gleam_00.png"; | |||
| 38890 | break; | |||
| 38891 | case 1: | |||
| 38892 | skillGleam->path = "*#images/ui/HUD/HUD_NewSpell_Gleam_01.png"; | |||
| 38893 | break; | |||
| 38894 | case 2: | |||
| 38895 | skillGleam->path = "*#images/ui/HUD/HUD_NewSpell_Gleam_02.png"; | |||
| 38896 | break; | |||
| 38897 | case 3: | |||
| 38898 | skillGleam->path = "*#images/ui/HUD/HUD_NewSpell_Gleam_03.png"; | |||
| 38899 | break; | |||
| 38900 | case 4: | |||
| 38901 | skillGleam->path = "*#images/ui/HUD/HUD_NewSpell_Gleam_04.png"; | |||
| 38902 | break; | |||
| 38903 | default: | |||
| 38904 | break; | |||
| 38905 | } | |||
| 38906 | } | |||
| 38907 | } | |||
| 38908 | skillsFramePos.w = skillFramePos.x + skillFramePos.w; | |||
| 38909 | if ( skillUp.isSpell ) | |||
| 38910 | { | |||
| 38911 | skillsFramePos.w = std::max(skillsFramePos.w, skillBgCapImg->pos.x + skillBgCapImg->pos.w); | |||
| 38912 | } | |||
| 38913 | else | |||
| 38914 | { | |||
| 38915 | skillsFramePos.w = std::max(skillsFramePos.w, skillBgImg->pos.x + skillBgImg->pos.w); | |||
| 38916 | } | |||
| 38917 | skillStartX += skillSpacing; | |||
| 38918 | } | |||
| 38919 | ||||
| 38920 | int midpoint = 0; | |||
| 38921 | if ( skillPosX.size() > 1 ) | |||
| 38922 | { | |||
| 38923 | if ( skillPosX.size() % 2 == 1 ) | |||
| 38924 | { | |||
| 38925 | midpoint = skillPosX[size_t(skillPosX.size() / 2)]; | |||
| 38926 | } | |||
| 38927 | else | |||
| 38928 | { | |||
| 38929 | size_t midIndex1 = std::max((size_t)0, (skillPosX.size() / 2) - 1); | |||
| 38930 | size_t midIndex2 = (skillPosX.size() / 2); | |||
| 38931 | midpoint = skillPosX[midIndex1] + (skillPosX[midIndex2] - skillPosX[midIndex1]) / 2; | |||
| 38932 | } | |||
| 38933 | skillsFramePos.x -= midpoint; | |||
| 38934 | } | |||
| 38935 | else if ( skillPosX.size() == 1 ) | |||
| 38936 | { | |||
| 38937 | skillsFramePos.x -= skillPosX[0]; | |||
| 38938 | } | |||
| 38939 | else | |||
| 38940 | { | |||
| 38941 | skillsFramePos.x -= skillsFramePos.w / 2; | |||
| 38942 | } | |||
| 38943 | /*if ( skillsFramePos.x % 2 == 1 ) | |||
| 38944 | { | |||
| 38945 | ++skillsFramePos.x; | |||
| 38946 | }*/ | |||
| 38947 | skillsFrame->setSize(skillsFramePos); | |||
| 38948 | if ( ticks != skillUp.processedOnTick ) | |||
| 38949 | { | |||
| 38950 | skillUp.processedOnTick = ticks; | |||
| 38951 | if ( skillUp.preDelayTicks > 0 ) | |||
| 38952 | { | |||
| 38953 | --skillUp.preDelayTicks; | |||
| 38954 | } | |||
| 38955 | else | |||
| 38956 | { | |||
| 38957 | ++skillUp.ticksActive; | |||
| 38958 | } | |||
| 38959 | } | |||
| 38960 | ||||
| 38961 | static ConsoleVariable<int> cvar_skillup_framey("/skillup_framey", 48); | |||
| 38962 | int framey = *cvar_skillup_framey; | |||
| 38963 | if ( players[player]->bUseCompactGUIHeight() && players[player]->shootmode ) | |||
| 38964 | { | |||
| 38965 | framey -= 28; | |||
| 38966 | framey = std::max(4, framey); | |||
| 38967 | } | |||
| 38968 | SDL_Rect levelUpFramePos{ hud_t.hudFrame->getSize().w / 2 - frameWidth / 2, framey, | |||
| 38969 | frameWidth, skillsFramePos.y + skillsFramePos.h }; | |||
| 38970 | levelUpFramePos.x += players[player]->camera_virtualx1(); | |||
| 38971 | levelUpFramePos.y += players[player]->camera_virtualy1(); | |||
| 38972 | levelUpFramePos.y += skillUp.fadeout * *cvar_skillup_falldist; | |||
| 38973 | if ( players[player]->bUseCompactGUIWidth() || players[player]->bUseCompactGUIHeight() ) | |||
| 38974 | { | |||
| 38975 | levelUpFramePos.y += -16; | |||
| 38976 | } | |||
| 38977 | hud_t.skillupFrame->setSize(levelUpFramePos); | |||
| 38978 | ||||
| 38979 | if ( skillUp.ticksActive >= skillUp.ticksToLive ) | |||
| 38980 | { | |||
| 38981 | skillUp.expired = true; | |||
| 38982 | } | |||
| 38983 | } |